- 為何使用grunt?
- 如何搭建grunt?
- 開始第一個grunt項目 基礎()合並js文件
- 開始第一個grunt項目 基礎()壓縮js
- 開始第一個grunt項目 基礎()代碼規范檢測
- 開始第一個grunt項目 基礎()開啟自動檢測
- 開始第一個grunt項目 提高()Js模塊化之browserify
- 開始第一個grunt項目 提高()單元測試
- 開始第一個grunt項目 提高()自動為代碼生成API文檔
- 小技巧
為何使用grunt?
一句話:自動化。對於需要反復重復的任務,例如壓縮(minification)、編譯、單元測試、linting等,自動化工具可以減輕你的勞動,簡化你的工作。
Grunt生態系統非常龐大,並且一直在增長。由於擁有數量龐大的插件可供選擇,因此,你可以利用Grunt自動完成任何事,並且花費最少的代價。
常用插件
-
grunt-contrib-uglifybyJs壓縮插件
-
grunt-contrib-cssminbyCss壓縮插件
-
grunt-contrib-jshintbyJs代碼檢測插件:檢測標注javascript代碼中的出錯和規范問題
-
grunt-contrib-watch監控文件插件:每當文件發生修改,自動運行grunt任務,如自動檢測代碼
-
grunt-jsdoc文檔生成插件:根據項目自動生成js文檔
-
grunt-browserifyjavascript模塊管理,browserify使用node comnonjs規范,讓前端也能使用15萬個node插件
-
grunt-karma單元測試框架
-
jasmine-core單元測試內核
-
phantomjs單元測試模擬環境
如何搭建grunt?
安裝准備:
1.下載安裝NodeJs
2.將NodeJs資源提取路徑 從NPM移到CNPM,CNPM下載點在國內,速度更快。
npm install -g cnpm --registry=https://registry.npm.taobao.org
3.在任意位置新建文件夾demo
開始安裝Grunt:
cnpm install -g grunt-cli
先將Grunt命令行(CLI)安裝到全局環境中。安裝時可能需要使用sudo(針對OSX、*nix、BSD等系統中)權限或者作為管理員(對於Windows環境)來執行以下命令。
注意:安裝grunt-cli並不等於安裝了 Grunt!Grunt CLI的任務很簡單:調用與Gruntfile在同一目錄中 Grunt。這樣帶來的好處是,允許你在同一個系統上同時安裝多個版本的 Grunt。添加 Grunt 項目配置文件夾
在demo文件夾中添加兩份文件:package.json 和 Gruntfile。
package.json: 此文件被npm用於存儲項目的元數據,以便將此項目發布為npm模塊。你可以在此文件中列出項目依賴的grunt和Grunt插件,放置於devDependencies配置段內。
{ "name": "my-project-name", "version": "0.1.0", "devDependencies": { } }
Gruntfile.js: 此文件被命名為 Gruntfile.js 或 Gruntfile.coffee,用來配置或定義任務(task)並加載Grunt插件的。
安裝Grunt
cnpm install grunt --save-dev
進入下一章節
開始第一個grunt項目 基礎(一)合並js文件
安裝grunt插件:grunt-contrib-concat
cnpm install grunt-contrib-concat --save-dev
創建代碼開發(src)和構建(build)文檔
—demo |-build |-src |-Gruntfile.js |-package.js
配置grunt配置文件Gruntfile.js
module.exports = function(grunt) { // Grunt 配置. grunt.initConfig({ concat: { options: { //定義一個字符串插入每個文件之間用於連接輸出 separator: ';' }, dist: { src: ['src/*.js'], dest: 'build/main.total.js', } } }); // 加載包含 "uglify" 任務的插件。grunt.loadNpmTasks('grunt-contrib-concat'); // 默認被執行的任務列表。 grunt.registerTask('default', ['concat']); };
運行grunt,構建代碼
grunt
進入下一章節
開始第一個grunt項目 基礎()壓縮js
安裝grunt插件:grunt-contrib-uglify
cnpm install grunt-contrib-uglify --save-dev
配置grunt配置文件Gruntfile.js
module.exports = function(grunt) { //Grunt 配置. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), //合並js concat: { options: { //定義一個字符串插入每個文件之間用於連接輸出 separator: ';' }, dist: { src: ['src/*.js'], dest: 'build/main.total.js', } }, //壓縮js uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'build/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } }, }); // 加載包含 "concat" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-concat'); // 加載包含 "uglify" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-uglify'); // 默認被執行的任務列表。 grunt.registerTask('default', ['concat','uglify']); };
運行grunt,構建代碼
grunt
進入下一章節
開始第一個grunt項目 基礎()代碼規范檢測
安裝grunt插件:grunt-contrib-jshint
cnpm install grunt-contrib-jshint --save-dev
配置grunt配置文件Gruntfile.js
module.exports = function(grunt) { // Project configuration. grunt.initConfig({pkg: grunt.file.readJSON('package.json'), //合並js concat: { options: { //定義一個字符串插入每個文件之間用於連接輸出 separator: ';' }, dist: { src: ['src/*.js'], dest: 'build/main.total.js', } }, //壓縮js uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'build/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } }, //代碼檢測 jshint: { files: ['src/*.js'], options: { "strict": true, "globalstrict" : true, "node":true, "browser":true, globals: { exports: true } } } }); // 加載 "concat" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-concat'); // 加載 "uglify" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-uglify'); // 加載包含 "jshint" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-jshint'); // 默認被執行的任務列表。 grunt.registerTask('default', ['concat','uglify','jshint']); };
運行grunt,構建代碼
grunt
開始第一個grunt項目 基礎()開啟自動檢測
安裝grunt插件:grunt-contrib-watch
cnpm install grunt-contrib-watch --save-dev
配置grunt配置文件Gruntfile.js
module.exports = function(grunt) { // Project configuration. grunt.initConfig({pkg: grunt.file.readJSON('package.json'), //合並js concat: { options: { //定義一個字符串插入每個文件之間用於連接輸出 separator: ';' }, dist: { src: ['src/*.js'], dest: 'build/main.total.js', } }, //壓縮js uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'build/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } }, //代碼檢測 jshint: { files: ['src/*.js'], options: { "strict": true, "globalstrict" : true, "node":true, "browser":true, globals: { exports: true } } }, watch: { scripts: { files: ['<%= jshint.files %>'], tasks: ['jshint'], options: { spawn: false, }, }, }, }); // 加載包含 "concat" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-concat'); // 加載包含 "uglify" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-uglify'); // 加載包含 "jshint" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-jshint'); // 加載包含 "watch" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-watch');//grunt watch // 默認被執行的任務列表。 grunt.registerTask('default', ['concat','uglify','jshint']); };
開啟自動檢測
grunt watch
這時候修改src文件夾中內容,則會自動檢測代碼
開始第一個grunt項目 提高()Js模塊化之browserify
安裝grunt插件:grunt-browserify
cnpm install grunt-browserify --save-dev
配置grunt配置文件Gruntfile.js
module.exports = function(grunt) { // Project configuration. grunt.initConfig({pkg: grunt.file.readJSON('package.json'), //合並js concat: { options: { //定義一個字符串插入每個文件之間用於連接輸出 separator: ';' }, dist: { src: ['src/*.js'], dest: 'build/main.total.js', } }, //壓縮js uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'build/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } }, //代碼檢測 jshint: { files: ['src/*.js'], options: { "strict": true, "globalstrict" : true, "node":true, "browser":true, globals: { exports: true } } }, watch: { scripts: { files: ['<%= jshint.files %>'], tasks: ['jshint'], options: { spawn: false, }, }, }, browserify: { options: { browserifyOptions: { debug: true } }, demo:{ files: { './src/app/build/app.js': ['./src/app/app.main.js'] } } }, }); // 加載包含 "concat" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-concat'); // 加載包含 "uglify" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-uglify'); // 加載包含 "jshint" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-jshint'); // 加載包含 "watch" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-watch');//grunt watch //加載包含 "browserify" 任務的插件。 grunt.loadNpmTasks('grunt-browserify'); // 默認被執行的任務列表。 grunt.registerTask('default', ['concat','uglify','jshint']); grunt.registerTask('app', ['browserify:demo']); };
創建demo的js文件
app.main.js、a.js
—demo |-build |-index.html |-src |-app.main.js |-a.js |-Gruntfile.js |-package.js
app.main.js
'use strict'; var A=require("./a"); function app(){ this.a=new A(); } app.prototype={ init : function () { this.a.say(); } }; module.exports=app; var base = new app(); base.init();
a.js
'use strict'; function a(){ } a.prototype={ say : function () { console.log("hello world!"); } }; module.exports=a;
index.html
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <meta name="manifest" content="version.json|manifest.json" /> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport" /> <meta content="telephone=no" name="format-detection" /> <title>平安</title> </head> <body> <header></header> <div id="main">123</div> <div id="cover"></div> <script src="./app.js"></script> </body> </html>
編譯開發代碼生成上線代碼
grunt app
開始第一個grunt項目 提高()單元測試
安裝grunt插件:grunt-karma,karma-browserify,karma-jasmine
cnpm install grunt-karma --save-dev cnpm install karma-browserify --save-dev cnpm install karma-jasmine --save-dev
配置grunt配置文件Gruntfile.js
module.exports = function(grunt) { // Project configuration. grunt.initConfig({pkg: grunt.file.readJSON('package.json'), //合並js concat: { options: { //定義一個字符串插入每個文件之間用於連接輸出 separator: ';' }, dist: { src: ['src/*.js'], dest: 'build/main.total.js', } }, //壓縮js uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'build/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } }, //代碼檢測 jshint: { files: ['src/*.js'], options: { "strict": true, "globalstrict" : true, "node":true, "browser":true, globals: { exports: true } } }, watch: { scripts: { files: ['<%= jshint.files %>'], tasks: ['jshint'], options: { spawn: false, }, }, }, karma: { unit: { configFile: 'karma.conf.js' } }, browserify: { options: { browserifyOptions: { debug: true } }, demo:{ files: { './src/app/build/app.js': ['./src/app/app.main.js'] } } }, }); // 加載包含 "concat" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-concat'); // 加載包含 "uglify" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-uglify'); // 加載包含 "jshint" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-jshint'); // 加載包含 "watch" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-watch');//grunt watch //加載包含 "browserify" 任務的插件。 grunt.loadNpmTasks('grunt-browserify'); grunt.loadNpmTasks('grunt-karma');//grunt karma ***** // 默認被執行的任務列表。 grunt.registerTask('default', ['concat','uglify','jshint']); grunt.registerTask('app', ['browserify:demo']); };
創建單元測試的js文件
app.main.js、a.js
—demo |-build |-index.html |-src |-app.main.js |-a.js |-test |-unit.js |-demo.js |-Gruntfile.js |-karma.conf.js |-package.js
karma.conf.js
// Karma configuration // Generated on Wed Sep 16 2015 17:29:29 GMT+0800 (CST) module.exports = function(config) { config.set({ // base path that will be used to resolve all patterns (eg. files, exclude) basePath: '', // frameworks to use // available frameworks: https://npmjs.org/browse/keyword/karma-adapter frameworks: ['browserify','jasmine'], // list of files / patterns to load in the browser files: [ {pattern:'./test/**/*.js'} ], // list of files to exclude exclude: [ ], // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor preprocessors : { './test/**/*.js' : ['browserify'], }, // test results reporter to use // possible values: 'dots', 'progress' // available reporters: https://npmjs.org/browse/keyword/karma-reporter reporters: ['progress'], // web server port port: 9876, // enable / disable colors in the output (reporters and logs) colors: true, // level of logging // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG logLevel: config.LOG_INFO, // enable / disable watching file and executing tests whenever any file changes autoWatch: true, // start these browsers // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher browsers: ['PhantomJS'], // Continuous Integration mode // if true, Karma captures browsers, runs the tests and exits singleRun: false }) }
unit.js
var methods = require("../demo"); var methdo = new methods(); describe("methods tests", function () { it("should return 3", function () { expect(methdo.add(1,2)).toBe(3); }); it("should return 5", function () { expect(methdo.add(2,2)).toBe(4); }); });
demo.js
/** * Created by haoyuandai on 15/9/18. */ function math(){ } math.prototype={ add:function(a,b){ return a+b; } } module.exports = math;
運行單元測試
grunt karma
開始第一個grunt項目 提高()自動為代碼生成API文檔
安裝grunt插件:grunt-jsdoc
cnpm install grunt-jsdoc --save-dev
配置grunt配置文件Gruntfile.js
module.exports = function(grunt) { // Project configuration. grunt.initConfig({pkg: grunt.file.readJSON('package.json'), //合並js concat: { options: { //定義一個字符串插入每個文件之間用於連接輸出 separator: ';' }, dist: { src: ['src/*.js'], dest: 'build/main.total.js', } }, //壓縮js uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'build/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } }, //代碼檢測 jshint: { files: ['src/*.js'], options: { "strict": true, "globalstrict" : true, "node":true, "browser":true, globals: { exports: true } } }, watch: { scripts: { files: ['<%= jshint.files %>'], tasks: ['jshint'], options: { spawn: false, }, }, }, karma: { unit: { configFile: 'karma.conf.js' } }, browserify: { options: { browserifyOptions: { debug: true } }, demo:{ files: { './src/app/build/app.js': ['./src/app/app.main.js'] } } }, //生成API文檔 jsdoc : { dist : { src: ['src/*.js'], options: { destination: 'doc' } } } }); // 加載包含 "concat" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-concat'); // 加載包含 "uglify" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-uglify'); // 加載包含 "jshint" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-jshint'); // 加載包含 "watch" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-watch');//grunt watch //加載包含 "browserify" 任務的插件。 grunt.loadNpmTasks('grunt-browserify'); grunt.loadNpmTasks('grunt-karma');//grunt karma ***** grunt.loadNpmTasks('grunt-jsdoc'); // 默認被執行的任務列表。 grunt.registerTask('default', ['concat','uglify','jshint']); grunt.registerTask('app', ['browserify:demo']); };
生成接口文檔
grunt jsdoc
小技巧
部分功能IE9以下可能不支持喲如何讓客戶端加載服務器字體文件?
css中@font-face 能夠加載服務器端的字體文件,讓客戶端顯示客戶端所沒有安裝的字體。
@font-face :{屬性: 取值;}
@font-face{ font-family://設置文本的字體名稱。 font-style://設置文本樣式。 font-variant://設置文本是否大小寫。 ont-weight://設置文本的粗細。 font-stretch://設置文本是否橫向的拉伸變形。 font-size://設置文本字體大小。 src://設置自定義字體的相對路徑或者絕對路徑,注意,此屬性只能在@font-face規則里使用。 }
如何在頁面做一條(小於1px)很細的線
body{ background-image: url("data:image/svg+xml;utf8, <svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100%'> <rect fill='#c1c1c1' x='0' y='0' width='0.75' height='100%'/> <rect fill='#c1c1c1' x='99.8%' y='0' width='0.75' height='100%'/> </svg>"); background-position-x: 0; background-position-y: 100%; background-repeat: no-repeat; border-bottom: 0; }
如何讓頁面在ios上滾動的順滑
添加css:
body{ -webkit-overflow-scrolling: touch; }
如何解決ios上點擊300毫秒延遲問題
使用fastclickJs模塊
<script type='application/javascript' src='/path/to/fastclick.js'></script> if ('addEventListener' in document) { document.addEventListener('DOMContentLoaded', function() { FastClick.attach(document.body); }, false); }
如何將特殊的表情字符傳到服務器上
使用nodeJs-base64 模塊
var base64=require('base64-coder-node')(); var name = 'emojsay%3fwqUds'; name= base64.encode(name);//string轉base64 name= base64.decode(name);//base64轉string
修復 iOS 下微信瀏覽器設置頁面標題未生效
/** * @function * @description 修復 iOS 下設置頁面標題未生效。調用方法,設置 document.title = 'Title';,后調用 updatePageTitleiOS(); * @memberof WeChatHelper.prototype */ function updatePageTitleIniOS(title){ ////iframe 加載后的回調函數 //function unloadHandler(){ //document.body.removeChild(ifrm); //} document.title = title; //創建 iframe var ifrm = document.createElement('iframe'); //iframe 指向圖標文件 ifrm.src = '/favicon.ico'; ifrm.style.position = 'absolute'; ifrm.style.top = '-1000px'; //綁定回調函數 //ifrm.addEventListener('load', unloadHandler); ifrm.addEventListener('load', function () { ifrm.removeEventListener('load'); setTimeout(function(){ document.body.removeChild(ifrm); },10); }); //添加 iframe 至文檔中 document.body.appendChild(ifrm); }
通過 冒泡 來監聽 父級元素下 多個自元素
loadList = document.getElementById("loadList");
loadList.addEventListener("click", function (e) {
var thisLi;
thisLi = e.target.parentNode.parentNode.parentNode;
var par = thisLi.className;
var items = par.toString().split(' ');
switch (items[1]) {
case "1":
var params = '{"idApplicant": "' + items[2] + '","claimType": "' + items[1] + '","toaTaskNo": "' + items[3] + '"}';
router.navigate("wcOnlineClaimInfo/" + params);
break;
case "2":
var params = '{"idApplicant": "' + items[2] + '","claimType": "' + items[1] + '","docuNo": "' + items[3] + '"}';
router.navigate("wcOfflineClaimInfo/" + params);
break;
}
}, true);
Doc中 Class 操作
javascript根據 class名稱 來獲取dom對象
getElementsByClassName('className')
classList操作
body.classList.length //獲取類名的數量 body.classList.item(num) //根據num獲取元素的類名 body.classList.add('className') //增加元素的類 body.classList.remove('className') //刪除元素的類 body.classList.contains('className') //檢測元素是否包含某個類 body.classList.toggle('className') //存在即刪除不存在即添加
掌控this
Function.prototype.bind的作用
this.a=1; document.body.addEventListener('click',function(e){ alert(e.target); alert(this.a);//undefined }); //document.body.addEventListener('click',function(e){ // alert(e.target); // alert(this.a);//1 //}.bind(this));