一步步構建自己的AngularJS(1)——項目初始化
來自: http://www.cnblogs.com/myzhibie/p/5224571.html
Angular1距離2009年發布已經好多年了,Angular2也已經出了Beta版,估計今年就能正式發布。大多數人對于Angular1.X的認識僅限于能夠在項目中使用,對于其中的深層原理知道的并不多。市面上也沒有特別好的介紹Angular實現原理的教程或者書籍。今天在看技術文檔的時候偶然發現了一本比較好的Angular底層原理書籍 《build your own AngularJS》 ,費了好大功夫買下了全本,隨之開始了Angular1.X的底層實現的探索之旅。本系列文章會按照書中的章節,每一章節獨立成為一篇文章,按書中的介紹一步步來動手實現自己的AngularJS,以便深入學習。本系列文章的目的主要是以更為簡單容易接受的方式讓讀者輕松學習整個過程而不用購買這本書(30多刀啊),同時記錄自己的學習過程,關于本系列的所有源代碼參見 這里 。
本文的主要內容是構建一個可運行的項目作為實現AngularJS的基礎代碼項目庫,初始化整個項目,包括代碼打包,模塊化,測試,代碼lint,使用NPM Scripts進行自動化腳本運行等,這些工作是今后實現的基礎。
1.建立項目并初始化package.json文件
首先確保你的機器上已經安裝了 NodeJS 和 NPM ,接著運行以下命令行
mkdir myangular cd myangular mkdir test mkdir src
首先創建項目根目錄myangular,然后在根目錄下創建test和src兩個文件夾,分別用來存放測試文件和源文件,接著輸入以下命令行
npm -y init
會在項目根目錄下創建一個package.json文件,用來存放NPM相關的配置信息。
2.創建源文件并啟用JSHint
對于一個框架的實現需要保證代碼一致性和遵循一定的規范,這就需要用到JSHint插件。首先在src文件夾下創建一個hello.js的文件,用來測試,內容如下:
function sayHello() {
return "Hello, world!";
}
接著輸入以下命令安裝JSHint
npm install --save-dev jshint
這會在項目根目錄下創建node_modules文件夾并將所有NPM install安裝的文件都放在這里。并在package.json的devDependencies配置項中加入一條關于JSHint的配置信息,表示這是在開發模式中需要加入的依賴包,在生產模式下不需要。接著在項目根目錄下創建一個.jshintrc文件,用來存放JSHint需要讀取的配置,它的內容如下:
{
"browser": true,
"browserify": true,
"devel": true
}
當我們運行JShint的時候,就會遵循這個配置文件下的信息來查看代碼是否符合規范。
接著在package.json文件中添加如下配置信息,用來運行JShint,檢查src目錄下的文件是否存在問題。
"scripts": {
"lint": "jshint src"
}
最后,使用如下命令行運行JSHint
npm run lint
3.為項目加入單元測試
在單元測試階段需要用到 Jasmine , karma 以及 Sinon.JS ,其中Jasmine是一個單元測試框架,karma是一個test runner,Sinon.js是需要用到的一個測試庫。
首先安裝Jasmine及Sinon.js
npm install --save-dev jasmine-core sinon
接著安裝karma及其相關插件
npm install --save-dev karma karma-jasmine karma-jshint-preprocessor
最后安裝Phantom.js作為瀏覽器的測試環境
npm install --save-dev phantomjs karma-phantomjs-launcher
以上都安裝完成之后需要對karma進行配置,在項目根目錄下創建一個karma.conf.js文件,其內容如下:
module.exports = function(config) {
config.set({
frameworks: ['jasmine'],
files: [
'src/**/*.js',
'test/**/*_spec.js'
],
preprocessors: {
'test/**/*.js': ['jshint'],
'src/**/*.js': ['jshint']
},
browsers: ['PhantomJS']
})
}
主要作用是告訴karma使用jasmine作為測試框架,需要測試的文件主要是src目錄和test目錄下的文件,在處理這些文件之前需要使用jshint進行預處理,同時測試的瀏覽器環境是PhantomJS.
由于我們需要在測試文件中使用全局變量諸如describe等,所以需要在.jshintrc文件中設置,修改該文件,其被修改的內容如下:
{
"browser": true,
"browserify": true,
"devel": true,
"globals": {
"jasmine": false,
"describe": false,
"it": false,
"expect": false,
"beforeEach": false,
"afterEach": false
}
}
接著修改package.json文件中的scripts配置項如下,用來運行自動化腳本。
"scripts": {
"lint": "jshint src test",
"test": "karma start"
}
這時,使用npm run lint就能夠運行JShint去檢測test和src文件夾下的文件是否符合語法規范,使用npm run test 就能運行全局的測試文件。
最后,在test文件夾下創建一個hello_spec.js文件,運來存放我們的測試用例,其內容如下:
describe("Hello", function() {
it("says hello", function() {
expect(sayHello()).toBe("Hello, world!");
});
});
這時運行npm test 就能運行hello_spec.js這個測試用例,在命令行中出現諸如以下的結果:
可以看出,它不僅有我們測試用例自身運行的結果,在測試用例運行的時候,還會啟動JSHint并將運行結果顯示出來。
4.為項目添加模塊化解決方案
由于Angular本身出現的較早,當時還沒有AMD,CommonJS等模塊化解決方案,所以它實際上是采用全局變量及函數直接定義整個代碼庫的,但是在該項目中我們使用CommonJS輔以browserify作為我們的模塊化解決方案。
首先安裝browserify及其相關插件
npm install --save-dev browserify karma-browserify
安裝成功后修改src目錄下的hello.js文件,讓其符合CommonJS格式,其內容如下:
module.exports = function sayHello() {
return "Hello, world!";
};
同時修改test目錄下的hello_spec.js文件,讓其符合CommonJS格式。
var sayHello = require('../src/hello');
describe("Hello", function() {
it("says hello", function() {
expect(sayHello()).toBe("Hello, world!");
});
});
最后,修改karma.conf.js讓其和browserify結合起來使用,修改后的內容如下:
module.exports = function(config) {
config.set({
frameworks: ['browserify', 'jasmine'],
files: [
'src/**/*.js',
'test/**/*_spec.js'
],
preprocessors: {
'test/**/*.js': ['jshint', 'browserify'],
'src/**/*.js': ['jshint', 'browserify']
},
browsers: ['PhantomJS'],
browserify: {
debug: true
}
})
}
配置中發生變化的主要是告訴karma使用browserify并且在進行測試前使用browserify進行預處理,同時啟用sourcemap便于程序debug.
5.為項目中添加Lodash和jQuery
Angular自身的實現是沒有jQuery的,但是由于我們更加關注的是Angular自身的實現而不是其對于Utility函數或者某些DOM操作的實現,所以為了簡化,這里使用Lodash來為我們提供對對象或者數組的處理,使用jQuery進行DOM查詢及操作。
npm install --save lodash jquery
安裝完成后,修改src目錄下的hello.js,其內容被修改為使用Lodash的方法如下:
var _ = require('lodash');
module.exports = function sayHello(to) {
return _.template("Hello, <%= name %>!")({name: to});
};
并修改test目錄下的hello_spec.js,如下:
var sayHello = require('../src/hello');
describe("Hello", function() {
it("says hello", function() {
expect(sayHello('Jane')).toBe("Hello, Jane!");
});
});
運行npm test可以看到測試的最終效果。
至此,我們已經搭建成了一個自己實現Angular的基礎環境,今后所有的代碼及實現都會在這個代碼庫中進行。所有的代碼都需要嚴格遵循JShint代碼規范并進行單元測試,接下來一起來進行Angular底層實現吧!PS:本項目的所有代碼在 這里 ,該系列文章會不定期更新。
</div>