Angular1距離2009年發佈已經好多年了,Angular2也已經出了Beta版,估計今年就能正式發佈。大多數人對於Angular1.X的認識僅限於可以在項目中使用,對於其中的深層原理知道的並很少。市面上也沒有特別好的介紹Angular實現原理的教程或者書籍。今天在看技術文檔的時候偶然發現了一本比較好的Angular底層原理書籍《build your own AngularJS》,費了好大功夫買下了全本,隨之開始了Angular1.X的底層實現的探索之旅。本系列文章會按照書中的章節,每一章節獨立成爲一篇文章,按書中的介紹一步步來動手實現本身的AngularJS,以便深刻學習。本系列文章的目的主要是以更爲簡單容易接受的方式讓讀者輕鬆學習整個過程而不用購買這本書(30多刀啊),同時記錄本身的學習過程,關於本系列的全部源代碼參見這裏。javascript
本文的主要內容是構建一個可運行的項目做爲實現AngularJS的基礎代碼項目庫,初始化整個項目,包括代碼打包,模塊化,測試,代碼lint,使用NPM Scripts進行自動化腳本運行等,這些工做是從此實現的基礎。html
1.創建項目並初始化package.json文件java
首先確保你的機器上已經安裝了NodeJS和NPM,接着運行如下命令行node
mkdir myangular cd myangular mkdir test mkdir src
首先建立項目根目錄myangular,而後在根目錄下建立test和src兩個文件夾,分別用來存放測試文件和源文件,接着輸入如下命令行jquery
npm -y init
會在項目根目錄下建立一個package.json文件,用來存放NPM相關的配置信息。git
2.建立源文件並啓用JSHintgithub
對於一個框架的實現須要保證代碼一致性和遵循必定的規範,這就須要用到JSHint插件。首先在src文件夾下建立一個hello.js的文件,用來測試,內容以下:npm
function sayHello() { return "Hello, world!"; }
接着輸入如下命令安裝JSHintjson
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:本項目的全部代碼在這裏,該系列文章會不按期更新。