AngularJS介紹–AngularJS的前世今生
AngularJS是什么
在Web開發領域,我們一般使用HTML作為前端頁面元素的聲明式語言,使用CSS技術作為展示樣式的描述語言,JavaScript作為業務處理交互的命令式語言。當我們構建非常復雜的Web應用時,純粹而有限的HTML就顯得非常不足,Javascript本身也會隨着項目代碼量的膨脹而難以維護和管理,研發工期和成本也會隨之難以控制。這時候,我們一般使用一些類庫(例如jQuery、Dojo等)或框架(例如Backbone、Ember、ExtJS等)來提升開發效率,進而降低項目的工期和成本,也方便后續的維護和管理。
而AngularJS不僅是一個理念先進(逼格高)的前端開發框架,更是一種端對端(End to End)的解決方案。AngularJS遵從架構設計中的MVC模式,提倡展現、數據和邏輯處理組件的松耦合(類似Flex和WPF)。AngularJS通過指令技術對傳統HTML實現了自然擴展,通過編譯技術實現了數據模型與展現視圖的雙向自動同步,從而消除了前端開發中繁瑣復雜的DOM操作(想想看那些一片片的selector)。最后再通過模塊化設計解決了JS代碼管理維護和按需加載的問題,解放了廣大前端程序員(以及后端程序員)同胞完成前端開發任務的生產力。而且這種解耦本身,也對前端的自動化測試技術提供了良好的支持。
AngularJS有多火
這兩年可以說是AngularJS受歡迎程度爆發性增長的兩年。AirPair做過一個三個主流JS框架AngularJS、Backbone、Ember的對比,AngularJS的熱度遠遠超過了另外兩個框架。參見下圖:
- 各網站上三種框架的統計數據(高出一大截)
- Google趨勢指數中的關注程度(甩出八百里)
AngularJS的設計理念
一句話來描述AngularJS的設計理念那就是:簡化對Web開發者的經驗要求,或者說讓Web開發變得簡單、同時讓Web本身變得功能更強。所以,AngularJS框架強調UI應該是用HTML聲明式的方式構建,數據和邏輯再進一步的由框架提供的機制自動匹配綁定。
作者Misco在采訪中表示,AngularJS框架的一些設計靈感來源於自己在Adobe公司從事的Flex開發經歷。
AngularJS的特點
- 上手簡單:通過學習AngularJS的一些概念和常見用法,即可在不需要大量了解DOM操作的情況下開發前端Web應用。
- 開發效率:一方面AngularJS相對於傳統前端開發能減少大量的操作代碼(雙向綁定、自動注入),另一方面也通過前后端分離、合理的模塊化組織項目結構降低了耦合、使開發者更關注於每一個具體的邏輯本身,從而加快了開發速度,也利於提升系統的質量。
- 運行效率:純靜態化便於前后端的緩存優化,按需加載也降低服務端IO的壓力。當然不得不提的是,如果雙向綁定的數據對象數據過多,比如多於2000個,會導致瀏覽器頁面的渲染速度較慢。對於這一點,由於一頁內展示可見的區域有限、並且用戶一個時間點能關注內容也有限,我們一般可以采用數據分頁加載等方式降低一次綁定的數據對象數量。
- 適用范圍:我們知道軟件領域沒有銀彈,沒有一種東西能解決一個大領域里的所有問題。所以,AngularJS也有自己的適用范圍。比如像Web游戲、在線圖形編輯等這些需要頻繁操作DOM的前端,就不適合用AngularJS來開發。一般來說,AngularJS特別適合基於CRUD的業務系統Web應用的前端開發,而且幸運的是目前這個地球上絕大部分的Web應用是這種。
起源
AngularJS最初由Misko Hevery和Adam Abrons於2009年開發,后來成為了Google公司的項目。后來Abrons離開了AngularJS,但在Google工作的Misko Hevery和谷歌員工Igor Minar和Vojta Jina等繼續開發和維護這個庫。
創始人Misko Hevery加入Google公司之前,曾在Intel、Xerox(施樂)、Sun和Adobe公司工作過,主要從事數據庫/后端方面的工作。加入Google公司后,Misko Hevery開始轉向自動化測試,AngularJS這項工作的主要目的是改進Google的開發者工作效率,從而改善代碼庫。
AngularJS的起源還有個有趣的小故事。最開始的時候,Misko Hevery和Adam Abrons搞了一個做在線JSON存儲服務的網站“GetAngular.com”,AngularJS就是為了這個項目開發的。雖然這個項目有了一些注冊用戶,但是兩人還是決定把AngularJS作為一個開源庫發行。2010年的時候,Misko Hevery參與Google Feedback項目。項目團隊使用GWT進行開發,在花了6個月的時候以后,編寫了17000行代碼。隨后,Misko Hevery花了3周將這17000行代碼的程序使用AngularJS重寫,結果是壓縮成了令人吃驚的1500行,不到原來的十分之一。這引起了Google的重視,公司也開始資助其團隊全職從事開發AngularJS。
后來的事兒,大家都知道了。AngularJS越來越火,有了更多的支持,吸引了來自全球的千百名開源愛好者為AngularJS項目做出了貢獻。隨着項目的發展和廣泛的傳播,越來越多的開發者在自己的項目中選擇使用AngularJS,學習和使用AngularJS已經成為了前端開發中的一股潮流。
這個JS庫為什么叫AngularJS?JS代碼的命名空間為什么叫ng?
官方的解釋是,因為HTML里普遍使用尖括號(英文叫Angular Brackets),而ng的發音跟Angular比較像。
但我們更傾向於認為 ng 是下一代(Next Generation)前端開發技術的意思。
現狀
AngularJS目前最新的穩定版本是1.3.0。(截止到北京時間2015年1月24日,最新穩定版本是1.3.10,beta版本最新的是1.4.0-beta.1。)1.3.0版本主要有3個變動:
- 去掉了對IE8的支持(雖然IE6和IE7早就連微軟自己都放棄治療了,AngularJS官方還是提出了一些對IE6、7、8的兼容辦法)
- 引入了單向數據綁定
- 刪掉了一堆過時的API(據說是為了AngularJS2.0版本做准備)
AngularJS核心特性–JS的四個現代化
MVC模式
MVC模式
大家應該都比較熟悉了。不管是Java里的Struts、spring MVC等框架,還是.Net里的ASP.NET MVC技術,都是典型的MVC模式。1979年,挪威計算機科學家、奧斯陸大學教授Trygve Reenskaug
為施樂公司的帕羅奧多研究中心(Xerox PARC)設計GUI(圖形用戶接口)軟件時(當時使用的是Smalltalk),正式提出了著名的MVC模式。
小八卦:Trygve Reenskaug的第一個主要的軟件項目“Autokon”,在1963年開始投入使用,此后在全世界的范圍內使用了30多年。
什么是MVC
MVC全稱是Model View Controller
,即模型(model)-視圖(view)-控制器(controller)的縮寫,即在項目設計和代碼結構里把業務和控制邏輯、數據模型、界面展示這三部分解耦,方便各部分單獨編寫和維護,而且在數據和界面發生變化時,對業務和控制邏輯影響最小,有時候甚至時不需要重新編寫業務和控制邏輯。由於有這樣的優點,MVC很快被廣泛應用到各種不同平台上的帶有業務處理的圖形化用戶界面中。
模型(Model)
:數據模型層,負責程序中數據邏輯的部分,一般主要是讀寫數據庫。這一塊對終端用戶是不可見的。
視圖(View)
:視圖展示層,負責將數據以交互界面的形式展現為終端用戶,視圖一般是基於數據模型來組織的。這一塊是軟件中終端用戶可以看到和操作的部分,比如前端開發使用HTML元素來實現UI界面。
控制器(Controller)
:邏輯控制層,負責處理業務邏輯和控制邏輯,處理視圖里的數據輸入,向模型層發送數據,從模型層獲取數據,將數據傳遞到視圖層進行展示等等。一般來說控制器充當模型和視圖的黏合劑角色。
MVC的優點
MVC模式的優點大概有如下幾條:
職責清晰
:MVC模式將原來都混在一起的復雜代碼邏輯按不同的職責拆解成三個不同的部分,每一部分的職責和功能都相對單一,便於獨立的設計和實現。代碼分層模塊化
:我們知道將一個系統按業務功能豎向划分,就產生了不同的業務模塊。而在同一個模塊內,基於職責的橫向拆解,項目代碼結構就實現了分層的模塊化(即我們常說的項目三層架構,3-Tier Architecture)。在這樣的橫切豎割以后,整個復雜的項目就被分解成了一個個非常小的模塊結構,使得項目研發工作的計划安排和管理都很方便。耦合性低
:將項目代碼結構拆解到非常小的粒度以后,各個小的模塊結構間依賴性降低,從而整個項目就降低了耦合性,整體復雜性也隨之降低了。可重用性高
:每個模塊獨立出來以后,抽象性更高,復用的可能性就更高。例如以前某個業務A中數據處理的代碼都更界面UI的代碼寫在一起,除非其他模塊B的數據和界面都跟一模一樣才能復用業務A的這一塊代碼。現在我們把業務A按照MVC都拆解開以后,只要業務B的數據模型用的還是業務A背后的數據模型D,我們就可以在實現業務B的時候,把數據模型D復用、而不是重新寫一遍。同理,視圖層的一些表單經常也可以復用到不同的業務模塊中去。可維護性高
:代碼干凈了,不拖泥帶水,發生變更時影響的范圍最小,方便維護。結構清晰了,每塊代碼寫到相應的目錄結構下,有利於整個團隊的項目大規模協同工作,同時新人加入團隊或是新的團隊接手項目,都會比較順利。研發成本低
:由於以上的優勢,在項目規模比較大,UI和邏輯都相對復雜的情況下,MVC模式能明顯地降低研發成本。
小提示:為什么GoF的23個設計模式中沒有MVC模式?
大家可以上網搜索一下,有驚喜哦! :)
AngularJS的MVC
我們先看一個Hello Angular
的小例子,然后基於例子了解下AngularJS中的MVC是怎么樣的。
HelloAngular_MVC.html
文件:
1 <!doctype html> 2 <html ng-app> 3 <head> 4 <meta charset="utf-8"> 5 </head> 6 <body> 7 <div ng-controller="HelloAngular"> 8 <p>{{greeting.text}},Angular</p> 9 </div> 10 </body> 11 <script src="js/angular-1.3.0.js"></script> 12 <script src="HelloAngular_MVC.js"></script> 13 </html>
HelloAngular_MVC.js
文件:
1 function HelloAngular($scope) { 2 $scope.greeting = { 3 text: 'Hello' 4 }; 5 }
例子由兩個文件組成,一個html文件,一個js文件。
這個html文件中除了要引入對應的js文件,還需要引入angular-1.3.0.js文件(可以在官網下載,也可以直接下載本書的示例代碼包,其中包含了所有的例子代碼和所需要的angular等依賴文件)。
我們可以看到在html文件中,有一個ng-controller,它的值為HelloAngular,而在js文件中定義了一個叫HelloAngular的函數。顯然,這個js文件中定義的HelloAngular函數,就是MVC中的C,控制器(Controller)
。
那MVC中的V,也就是視圖(View)
在哪兒呢?我們前面提到對用戶展示的可見內容就是視圖。那么我們在html文件中可以發現,p標簽里就是我們對外展示的內容,那么p標簽就是我們這個示例程序中的視圖,也就是如下這句代碼:
1 <p>{{greeting.text}},Angular</p>
MVC中的C和V都有了,那么M,也就是模型(Model)
在哪里呢?在html文件的視圖,也就是p標簽里,我們看到用雙花括號綁定了一個表達式greeting.text
,那么這個東西是哪兒來的呢?讓我們回到js文件中,可以看到有一個賦值:
1 $scope.greeting = { 2 text: 'Hello' 3 };
這句代碼是說,在$scope里,給greeting對象的text屬性賦值為字符串Hello
。視圖中將要使用的數據是從這里引入的。所以,這個賦值就充當了MVC中的模型M的角色。至此,我們的第一個AngularJS示例程序中的MVC結構就齊備了。
讓我們在瀏覽器里運行一下HelloAngular_MVC.html
看看效果:
可以看到展示出來的Hello,Angular
,其中的Hello
在html文件中並沒有這個字符串,說明它就是來源於我們js中對模型的賦值。
回顧一下本示例中MVC的各部分:
控制器
:js中實現的、在html里的函數。視圖
:html中展示內容的p標簽。模型
:js里給綁定對象賦值的部分。
模塊化
在上一節的例子里,我們可以發現定義的控制器HelloAngular
是一個全局的JS函數。大家都知道大量地定義一些全局的函數和變量,會污染JS的全局上下文環境。那么AngularJS里怎么解決這個問題的呢?答案就是模塊化。
什么是模塊化
在C++、Java里,我們通過Namespace、Package的方式隔離開了相同類名的類,而在Python里,我們可以進一步的使用Module來聚合一定功能的代碼。這些設計使得我們可以按照自己的需要放置某些類在同樣的一個層級組織之下。在AngularJS里,我們也可以顯式的定義一個模塊(Module)
,然后將某個功能模塊的所有邏輯代碼(函數、變量等),按照一定的規則和結構封裝到這個Module中,從而規范了項目結構的組織方式,同時也避免了全局環境污染。
小貼士:雖然模塊化約束了代碼中函數和變量的作用范圍和使用方式,但是AngularJS的Module里通過依賴注入的方式,可以使得我們的代碼更加的靈活方便。
AngularJS里的Module
我們先舉個栗子,看看AngularJS中Module的定義和用法。
1 HelloAngular_Module.html文件: 2 3 <!doctype html> 4 <html ng-app="HelloAngular"> 5 <head> 6 <meta charset="utf-8"> 7 </head> 8 <body> 9 <div ng-controller="helloAngular"> 10 <p>{{greeting.text}},Angular</p> 11 </div> 12 </body> 13 <script src="js/angular-1.3.0.js"></script> 14 <script src="HelloAngular_Module.js"></script> 15 </html> 16 HelloAngular_Module.js文件: 17 18 var myModule = angular.module("HelloAngular", []); 19 20 myModule.controller("helloAngular", ['$scope', 21 function HelloAngular($scope) { 22 $scope.greeting = { 23 text: 'Hello' 24 }; 25 } 26 ]);
我們可以看到,相比上一節的例子,html文件有一個微小變化:
- html標簽里多了一個屬性:
<html ng-app="HelloAngular">
,這個屬性告訴AngularJS框架,本頁面使用HelloAngular
這個模塊來啟動。
相比上一節的例子,js文件里有兩個變化:
- 多了一個模塊的定義代碼:
var myModule = angular.module("HelloAngular", [])
。這句代碼使用angular.module
方法定了一個名字叫HelloAngular
的模塊,並把這個模塊賦值給了myModule
變量。 - 多了一個Controller的顯式聲明:
myModule.controller("helloAngular", ['$scope' ...
。這里在使用myModule
的controller
方法,給HelloAngula
r模塊添加了一個helloAngular
的控制器。這樣,helloAngular
函數就變成了控制器定義時的一個內部函數。(這段代碼請注意區分HelloAngular首字母的大小寫。)
我們可以看到,AngularJS通過將Controller等資源聚合到一個顯式定義的Module,從而避免了全局環境的污染。這個例子也可以從另一個方面說明我們修改了控制器層,但是視圖層幾乎不受到影響。
讓我們在瀏覽器里運行一下HelloAngular_Module.html
看看效果:
可以看到與上一節例子的運行效果相同。
小貼士:示例代碼里還有一個值得一提的地方,就是
myModule.controller
創建控制器的時候,傳遞了一個'$scope'
參數,而后面的控制器函數聲明里使用了一個叫$scope
參數,這個參數會在控制器函數被調用時自動作為參數注入到函數。這就是AngularJS的依賴注入
。熟悉后端Web開發的同學們可以參考Spring MVC
中的參數自動注入。
Module在AngularJS中的重要性
大家在開始學習時可能會覺得AngularJS中有很多概念,有Module、有Directive、有Service、有Filter等等。大家一定要抓住一個點,一切都是從Module開始的。開始使用AngularJS開發時,要先考慮Module,只有先有了一個Module,才能在模式上調用Service、調用Directive等。這就是為什么AngularJS中Module很重要的原因。
指令系統
指令系統(Directive)
可以說是AngularJS中最有特色、最吸引人的功能特性。
AngularJS中的指令(Directive)
HelloAngular_Directive.html
文件:
相對於前面的例子,有兩個不同的地方:
- 在
HelloAngular_Directive.html
文件中,我們在原來用p標簽實現視圖的地方,加了一個<hello></hello>
標簽。 - 在
HelloAngular_Directive.js
文件中,在模塊里使用directive
方法創建了一個解釋hello
標簽的函數,使用<div>Hi everyone!</div>
作為模版來渲染hello
標簽。
在瀏覽器中運行HelloAngular_Directive.html
,效果如下:
可以看到頁面輸出了Hi everyone!
。按F11打開瀏覽器的調試功能,可以看到現在的源碼:
這說明頁面上的hello
標簽,已經被<div>Hi everyone!</div>
替換掉了。
小貼士:示例代碼中的restrict: ‘E’和replace: true的作用會在后面Directive的章節里詳細的講解。
指令(Directive)的好處
正常的html里寫hello標簽是不會被瀏覽器處理的,而在AngularJS里這么寫就可以實現自定義的標簽處理實現指令系統,這就像是JSP技術里的標簽庫。這樣我們可以根據自己的需要,封裝出來很多功能組件,做一大堆指令在需要的時候調用。
小貼士:每個html示例代碼中的開頭都有
<html ng-app="HelloAngular">
,其中的ng-app
就是AngularJS自定義的指令。那么這個指令是干什么的呢?我們知道每個程序都有一個入口點,比如Java的main函數。AngularJS檢測到html標簽里有
ng-app
這個指令時,就知道往后的所有內容都歸AngularJS來管了。既然是入口點那么每個程序只能有一個,所以ng-app
指令在每個單頁的AngularJS應用中只能出現一次。
雙向數據綁定
AngularJS的第四個核心特性就是雙向數據綁定,就是說數據模型層的變量可以綁定到前端視圖層的內容上、前端視圖層的內容上的數據也可以自動同步到數據模型層中去。目前大部分前端框架都只是實現了單向的數據綁定,比如jQueryUI、BackBone、Flex等。這也是吸引很多人使用AngularJS的一個重要原因。
BackBone官方網站上解釋自己不實現雙向數據綁定的原因是因為雙向數據綁定機制用得比較少。
單向數據綁定機制
我們先來看看經典的單向數據綁定處理流程:在單向數據綁定中我們一般先實現一個模板(Template)
,再實現我們的數據模型(Model),這里的數據可能是從后端服務器讀取出來的。然后通過數據綁定機制,把模板和數據結合在一起,生成一段html標簽,最后把html片段插入到文檔流里面。
我們可以發現,這個處理模式中,html片段一旦生成就無法再改變了:如果有新的數據過來,我們只能先清空原先的內容,把這個處理流程整個重新執行一遍。我們使用JQuery等框架就會有這些的一些問題。
雙向數據綁定機制
AngularJS認為單向綁定的處理模式非常的不優雅,所以就設計實現了雙向的數據綁定機制。AngularJS認為視圖和模型應該是綁定在一起的:當視圖發生變化的時候,模型也自動發生變化;當模型發生變化的時候,視圖自動會刷新顯示新的內容。很顯然這里需要借助一個事件機制來實現雙方的協調一致。AngularJS一直監聽數據和視圖的變動事件,並在事件發生時將一方的變動內容同步到另一方,從而實現動態的、局部的、實時的刷新。
什么樣的視圖最容易發生變化呢?
一般情況下,我們在視圖層使用表單收集用戶錄入的數據,所以表單這種視圖是最容易發生變化的。
AngularJS的雙向數據綁定示例
最后我們通過一個例子來演示AngularJS中的雙向數據綁定。
HelloAngular_TwoWayDataBinding.html
文件:
1 <!doctype html> 2 <html ng-app> 3 <head> 4 <meta charset="utf-8"> 5 </head> 6 <body> 7 <div> 8 <input ng-model="greeting.text"/> 9 <p>{{greeting.text}},AngularJS</p> 10 </div> 11 </body> 12 <script src="js/angular-1.3.0.js"></script> 13 </html>
示例代碼里,我們使用一個greeting.text表達式同時綁定到一個文本框和一個p標簽,從而實現這個文本框和p標簽的數據保持聯動刷新,文本框內容變化時,p標簽自動同步。
在瀏覽器中運行HelloAngular_TwoWayDataBinding.html
文件,然后在文本框中輸入文字,效果跟我們的預期一致。
前端開發環境介紹–工欲善其事必先利其器
人類學會使用工具,從而解放了生產力,創造了整個文明。對於我們前端技術人員來說,一套順手的工具,就像是行走江湖的大俠隨身帶了一口削鐵如泥的寶刀,解放我們的雙手和大腦,讓我們可以把更多寶貴的時間和精力放到創造更美好的應用上。本節我們就來看看怎么打造一款適合AngularJS開發的前端工具箱。
前端自動化測試工具的示例
我們可以先看看前端自動化測試工具的例子:
安裝Git、NodeJS、NPM、Bower、Protractor、Chrome等工具的例子先略過,本節后面會詳細講解。
從Github下載官方測試項目angular-phonecat
的源碼到本地目錄:
git clone https://github.com/angular/angular-phonecat
在打開一個命令行窗口,在源碼所在目錄執行:
npm start
效果如下:
在打開一個命令行窗口,在源碼所在目錄執行:
npm run protractor
效果如下:
Protractor配置完成后,自動打開Chrome瀏覽器執行前端測試腳本,可以看到自動執行測試的效果跟人工操作界面是完全一樣的:
執行完以后可以在啟動Protractor的控制台看到測試所消耗的時間為27.392秒,執行了7個測試用例,11個斷言,失敗了0個:
1 selenium standalone is up to date. 2 chromedriver is up to date. 3 4 > angular-phonecat@0.0.0 protractor D:\kk\git\angular-phonecat 5 > protractor test/protractor-conf.js 6 7 Using ChromeDriver directly... 8 ....... 9 10 Finished in 21.392 seconds 11 7 tests, 11 assertions, 0 failures
同時可以在啟動http-server的控制台看到所有的瀏覽器請求:
前端需要什么樣的開發環境
在實際搭建拉風的開發環境之前,我們先來看看為什么前端需要一套工具,需要什么樣的工具。
我們知道像后端Java開發,有Eclipse/MyEclipse、IntellJ IDEA、NetBeans這樣的神器,像Dotnet開發有Visual Studio.Net這種重量級的核武器。而前端開發領域里連一款像樣的調試器都沒有。砍柴不誤磨刀工,所以打造一身好裝備就是一個非常緊迫的任務。我們來看看,整個前端開發過程中,需要哪些工具:
-
代碼編輯工具:它應該足夠強大、靈活,響應速度快,支持各種語法高亮、提示、格式化等能加速我們把腦袋中的想法落地實現的功能特性。
-
斷點調試工具:這個是很顯然的,代碼編寫過程中,我們需要花大量的時間做跟蹤調試,驗證是不是符合我們的預期,中間變量和表達式的是不是正確等等。方便的調試工具最能節省編碼時間。
-
版本管理工具:把所有的開發代碼放到版本管理庫,記錄下來所有人對項目文件的增加、刪除、修改和合並操作,誤刪文件這種低級失誤從此再也不會出現了(經理再也不用擔心我的代碼了!)。同時也利於多人的團隊協作開發,以及多個版本同時開發維護。所以,我們也需要一款好用的版本管理工具。
-
代碼合並和混淆工具:代碼混淆工具像其他語言(Java和Dotnet等)也都會用到,混淆以后使得反編譯的代碼不具有可讀性,從而保護了我們的勞動成果,也防止壞人反向分析我們的業務邏輯,保護了我們應用系統的安全性。代碼合並工具是前端開發領域里一個比較獨特的東西,常見的非腳本語言一般都沒有(Java是編譯后生成jar包,Dotnet是編譯完就成了dll或exe文件,都不需要對源代碼進行打包)。
-
依賴管理工具:就像Java里的Maven、Dotnet里的NuGet,我們希望前端里也有一個工具可以幫我們管理項目的各種不同版本的依賴,自動下載、配置和更新。特別是項目比較大的時候,我們依賴了非常多的第三方庫,這時候如果沒有一個自動化的工具來管理這些依賴,每個依賴項都需要人工維護的話,很容易導致缺包、版本錯誤等問題,對項目本身就是一個災難。使用依賴管理工具的另外一個好處是,項目里不需要帶上各種依賴的庫,他們將會在構建項目時再從遠程依賴庫下載,這就減少了項目源碼環境的核心文件數量。
-
單元測試工具:一直以來,前端的單元測試都是一件非常困難的事情。因為前端的JS代碼常常會去操作頁面的DOM元素,所以測試代碼必須在瀏覽器環境下運行,我們的測試代碼脫離了瀏覽器環境就無法運行。后來NodeJS的出現,把這種不可能變成了現實,特別是對瀏覽器里的DOM元素也可以直接操作。
-
集成測試工具:當業務模塊功能完成以后,我們希望可以自動模擬用戶的輸入和點擊操作,模擬相關的業務功能,完成整個業務功能的自動化測試。
只要有了這樣一整套工具支撐前端代碼的開發,我們就可以擺脫刀耕火種的原始社會時代,進入現代社會的自動化、工業化時代!## 開發工具
本節為大家介紹最常見的11款前端開發工具。在實際項目中,這十一款神器不一定會全部都用到,大家可以根據具體的情況,適當地選擇自己所需要的進行搭配。本節我們先逐一介紹下這些工具,然后使用這些工具組裝一套完整而且“高大上”的前端開發環境。
如上圖所示的這11款工具中,NodeJS是其他工具的基礎,其他的絕大部分工具都是圍繞着NodeJS來實現的。在目前的前端領域的工具生態鏈里,NodeJS已經成為了整個生態環境的基石。
Sublime
Sublime是一款功能非常強大的文本編輯器(收費軟件、但是可以無限期試用)。官方網站地址為:http://www.sublimetext.com。進入官方網站首頁,可以看到常用的一些功能演示視頻。主要功能如下:
- 支持多種編程語言的語法高亮;
- 擁有優秀的代碼自動完成功能;
- 支持技術宅習慣的vim編輯模式,非常多的快捷鍵;
- 支持宏,可以把操作保存下來重放;
- 支持各種功能豐富的插件,在菜單里可以直接查看和安裝插件;
- 支持多標簽頁、多種布局和縮略圖;
- 支持文件導航、全屏編輯、列操作模式;
- 多重選擇,支持頁面中同時有多個光標,同時編輯多個位置;
- ……
一些非常高大上的功能:
- 軟件意外退出或突然崩潰時,不會丟失編輯內容(大家都有過記事本沒保存的經歷吧?);
- 加載比較大的文件,例如幾M的文件,非常流暢,不卡頓、不影響編輯。
- HTML代碼快速編碼(Zen Coding)功能。比如,如果我們要生成一個樣式為row的div,內部包含10個樣式為col-md-12的div,只需要輸入如下24個字符:
div.row>div.col-md-12*10
,然后使用快捷鍵Ctrl+E
,生成出來幾十倍的代碼,效果如下:
出現於2009年的Zen Coding技術,可能是廣大前端程序員最喜歡的功能了。熟悉JQuery選擇器語法的同學,應該能很快發揮這個神器的強大威力,將前端代碼開發變成既酷又爽的體驗過程。
WebStorm
代碼編輯工具,除了輕量級的Sublime,還有重量級的WebStorm。這款JetBrains出品的代碼編輯器,界面風格和使用方式跟IntelliJ IDEA完全一致,可以看做是IDEA針對Web前端開發的定制版本。使用過IDEA編輯器的同學可以快速上手使用。
當然Zen Coding、多光標編輯、vim操作、快捷鍵支持這些都少不了。除了常規的代碼編輯器功能以外,還有一些炫酷特性:
- 本地編輯歷史功能,所有的改動都不會丟失;
- 支持Git等版本管理工具,可以直接運行和調試;
- 支持NodeJS和NPM等前端工具集;
- 支持通過FTP方式部署代碼到服務器環境;
- 支持代碼格式化、代碼重構、代碼折疊、結構瀏覽等功能;
- 編寫HTML、CSS的時候,可以實時檢測代碼在各種不同瀏覽器下的兼容性如何;
- 有專門支持AngularJS開發的插件;
- ……
同樣展示下在WebStorm下的Zen Coding功能,新建一個test.html
文件,輸入div.row>div.col-md-12*10
,然后點擊Tab
鍵,效果如下:
WebStorm有非常多的功能特性和使用技巧,快捷鍵設置等等,需要的同學可以在網上自行搜索學習。WebStorm的功能比Sublime豐富的多,當然也更消耗資源,如果大家的開發機器配置比好的話,建議使用WebStorm進行開發。
AngularJS Batarang
斷點調試工具Batarang是Chrome瀏覽器的一個插件。Batarang的名稱來源於蝙蝠俠的蝙蝠標識,它是Chrome瀏覽器的一個插件。當然大家也可以使用傳統的斷點調試Firebug,但是Batarang的優勢在於它是專門針對AngularJS開發的調試器,內置了很多專門針對AngularJS的菜單和功能。
Chrome瀏覽器是Google公司基於Webkit內核、JavaScript V8引擎開發的瀏覽器,具有速度快,穩定不易奔潰,簡潔、安全,廣泛支持多種平台等功能特性。據StatCounter統計,2014年8月份,Chrome瀏覽器在中國的市場占有率以49.51%高居榜首,IE 瀏覽器排名第二位市場份額28%。可以說Chrome已經是目前最流行的瀏覽器了。
Batarang可以用如下兩種方式進行安裝:
第一種方式直接從Chrome中安裝:在Chrome瀏覽器的菜單中選擇“更多工具”-“擴展程序”進入擴展程序頁面,點擊“獲取更多擴展程序”;在Chrome網上應用店頁面,搜索AngularJS Batarang
,找到插件后點擊右上角的“免費”,然后按提示安裝即可。如果第一種方式比較慢的話,可以嘗試下面的第二種方式。
第二種方式從GitHub網站獲取AngularJS Batarang
發布的壓縮包進行安裝。首先從如下地址下載最新的zip壓縮包:
https://github.com/angular/angularjs-batarang/releases
解壓到本地文件夾,然后進入擴展程序頁面,勾選上開發者模式
,點擊加載正在開發的擴展程序...
,選擇解壓的文件夾,加載完Batarang插件后勾選上已啟用
即可。
使用方式:在打開要跟蹤調試頁面的Chrome瀏覽器里按F12,打開控制台,可以看到控制台里多一個AngularJS的標簽頁,此時即可使用Batarang的功能。
Git/TortoiseGit
Git是目前最流行的代碼版本管理工具。跟CVS、SVN最大的不同點應該是Git有本地代碼倉庫和遠程倉庫的概念,這樣我們一般情況下的的提交操作都是在本地倉庫進行的,只有我們顯示的執行遠程同步命令,Git才會把本地倉庫的代碼變化同步到Git服務器上的遠程倉庫、或是從Git服務器上的遠程倉庫同步到本地倉庫。
可以從官方網站下載Git的客戶端:
http://git-scm.com/download/
點擊對應平台的圖標下載安裝文件,下載完成后直接運行,即可安裝到系統。在命令行輸入如下命令:
1 git --version
輸出版本信息,則證明安裝成功:
1 git version 1.9.5.msysgit.0
此時就可以用git clone從GitHub或其他Git服務器下載項目代碼了。比如克隆AngularJS項目的源碼到本地:
1 git clone https://github.com/angular/angular.js
執行完成了以后,本地的代碼倉庫就有了一個AngularJS項目源碼的一個副本。可以修改,也可以添加文件到本地倉庫,例如添加一個叫test.js
的文件:
1 git add test.js
添加當前目錄下的所有新建文件到本地倉庫:
1 git add .
修改完了也可以提交到本地倉庫:
1 git commit test.js -m "add a test"
提交當前目錄下的所有變動過的文件:
1 git commit . -m "some reasons"
如果想要修改AngularJS的代碼后同步到GitHub網站,可以先在GitHub上把項目fork
到自己的倉庫里,然后clone到本地,修改后git commit
,最后再執行如下命令即可同步本地倉庫到GitHub遠程倉庫:
1 git push
如果其他人也修改了這個遠程倉庫,可以使用如下命令同步遠程倉庫到本地倉庫:
git pull
我們也可以使用如下命令查看本地代碼倉庫的未提交變動:
git status
或者使用如下命令查看代碼的所有修改記錄:
git log
特別地,我們可以只查看某個文件的最近幾條log,例如查看test.js
的最近2條修改記錄:
1 git log -2 test.js
如果你習慣於使用GUI界面的版本管理工具,特別是有過使用TortoiseSVN的經歷,則可以下載TortoiseGit使用。
可以從官方網站下載TortoiseGit:
1 http://download.tortoisegit.org/tgit/
安裝后,在任意文件夾中點擊右鍵,右鍵菜單就可以看到Git相關的操作,比如點擊Git Clone...
即可開始從服務器端clone項目代碼。如果想要使用中文的界面菜單,可以在下載頁面下載相應的中文語言包。
NodeJS
NodeJS目前對於前端開發整個生態圈的重要性,就無需累述了。大家可以從官方網站直接下載安裝:
http://nodejs.org/
NodeJS里有個非常給力的包管理器(NodeJS Package Manager,NPM
),通過NPM我們幾乎可以使用整個NodeJS生態圈的所有美妙工具和框架、類庫。NPM官方網址:
https://www.npmjs.com/
由於NPM現在是NodeJS自帶的工具。你也可以在這個頁面的左下方找到Install NPM
,進入下載頁面選擇合適的NodeJS版本進行下載安裝。安裝完了NodeJS就可以直接使用NPM來管理和安裝其他的庫了。
NPM使用一個叫package.json
的文件管理各種庫的元數據和依賴(類似Java項目中maven使用的pom文件)。我們一般把這個文件放到項目源碼的根目錄中,並在項目提交時一並提交到npm服務器。當我們在項目源碼根目錄執行npm install
時,NPM會分析此文件中的依賴項列表,並將它們都下載並加載到項目中。更多package.json
的信息可以參見:
https://docs.npmjs.com/files/package.json
小貼士:我們每次安裝依賴庫都訪問國外的npmjs主站可能會比較慢,幸好淘寶搭建了一個npm鏡像,通過如下命令即可配置以后使用淘寶的鏡像:
npm config set registry https://registry.npm.taobao.org
如果你有可用的vpn或代理服務器,則可以直接在命令行設置NPM使用的代理(其中代理服務器的ip和端口需要修改成你自己的):
set PROXY=http://localhost:8087
set HTTPS_PROXY=http://localhost:8087
關於NPM代表什么意思,官網
https://www.npmjs.com/
首頁的左上角會顯示各種不同的解釋,點擊一下就會換一種,比如Napping Panda Missionaries
、Never Poke Monkeys
、Node Package Manager
、nom, please more
等等。
這些解釋還有一個專門的GitHub項目,地址為:
安裝完NodeJS以后,可以執行如下命令進入基礎知識學習:
npm install -g learnyounode
返回如下信息:
C:\Program Files\nodejs\learnyounode -> C:\Program Files\nodejs\node_modules\learnyounode\learnyounode.js learnyounode@2.3.2 C:\Program Files\nodejs\node_modules\learnyounode ├── workshopper-boilerplate@0.0.1 ├── duplexer@0.1.1 ├── after@0.8.1 ├── rimraf@2.2.8 ├── through@2.3.6 ├── boganipsum@0.1.0 ├── hyperquest@0.2.0 (through@2.2.7) ├── chalk@0.4.0 (has-color@0.1.7, ansi-styles@1.0.0, strip-ansi@0.1.1) ├── colors-tmpl@0.1.1 (colors@0.6.2) ├── combined-stream@0.0.7 (delayed-stream@0.0.5) ├── workshopper-wrappedexec@0.1.2 (xtend@2.1.2) ├── through2@0.4.2 (xtend@2.1.2, readable-stream@1.0.33) ├── concat-stream@1.4.7 (inherits@2.0.1, typedarray@0.0.6, readable-stream@1.1.13) ├── through2-map@1.2.1 (through2@0.2.3, terminus@1.0.11) ├── workshopper-exercise@2.1.0 (tuple-stream@0.0.2, split@0.3.2, visualwidth@0.0.1, xtend@2.1.2, i18n-core@1.3.2) ├── stream-browserify@1.0.0 (inherits@2.0.1, readable-stream@1.0.33) ├── bl@0.7.0 (readable-stream@1.0.33) └── workshopper@2.2.0 (map-async@0.1.1, xtend@3.0.0, mkdirp@0.3.5, visualwidth@0.0.1, terminal-menu@1.0.2, optimist@0 .6.1, i18n-core@1.3.2, msee@0.1.1)
接着可以執行如下命令,開始學習NodeJS:
learnyounode
進入學習界面后,點擊鍵盤上的上下光標可以選擇菜單,回車進入課程。我們先進入最后的choose langguage
,選擇中文
,然后回車,即可看到界面已經變成中文:
選擇你好,世界
,點擊回車,接下來就可以按照教程學習:
Grunt
我們前面提到了為了保護我們的代碼、同時也為了節省網絡IO開銷而減小JS文件和降低文件數量,需要發布前端代碼時對多個JS文件進行合並壓縮和混淆。當然我們也不希望每次都得手動去做這件繁瑣的事兒,這時Grunt就是一個非常理想的選擇。NodeJS里的Grunt加上NPM基本上相當於Java里的Maven或Gradle、SBT。
可以直接使用npm安裝Grunt,在命令行下輸入:
npm install grunt
返回如下信息:
grunt@0.4.5 node_modules\grunt ├── dateformat@1.0.2-1.2.3 ├── which@1.0.8 ├── eventemitter2@0.4.14 ├── getobject@0.1.0 ├── colors@0.6.2 ├── rimraf@2.2.8 ├── async@0.1.22 ├── hooker@0.2.3 ├── grunt-legacy-util@0.2.0 ├── exit@0.1.2 ├── lodash@0.9.2 ├── underscore.string@2.2.1 ├── coffee-script@1.3.3 ├── iconv-lite@0.2.11 ├── grunt-legacy-log@0.1.1 (underscore.string@2.3.3, lodash@2.4.1) ├── glob@3.1.21 (inherits@1.0.0, graceful-fs@1.2.3) ├── nopt@1.0.10 (abbrev@1.0.5) ├── minimatch@0.2.14 (sigmund@1.0.0, lru-cache@2.5.0) ├── findup-sync@0.1.3 (lodash@2.4.1, glob@3.2.11) └── js-yaml@2.0.5 (esprima@1.0.4, argparse@0.1.16)
就會在當前目錄的node_modules文件夾下安裝grunt工具。如果加上-g參數,就可以把grunt安裝到NodeJS的全局目錄,所有的地方都可以使用這個工具了:
npm install -g grunt
如果加上-d參數,則同時將grunt所有依賴的庫都安裝上。
npm install -gd grunt
如果在當前項目里使用–save/–save-dev參數,則npm會更新更新package.json里的dependencies和devDepandencies配置:
npm install grunt -save
npm install grunt -save-dev
執行如下命令可以實現安裝Grunt命令行:
npm install -g grunt-cli
返回如下信息說明安裝成功:
C:\Program Files\nodejs\grunt -> C:\Program Files\nodejs\node_modules\grunt-cli\bin\grunt grunt-cli@0.1.13 C:\Program Files\nodejs\node_modules\grunt-cli ├── resolve@0.3.1 ├── nopt@1.0.10 (abbrev@1.0.5) └── findup-sync@0.1.3 (lodash@2.4.1, glob@3.2.11)
然后可以在命令行直接使用Grunt:
grunt --version
輸出如下信息:
grunt-cli v0.1.13
grunt v0.4.5
使用Grunt需要使用兩個配置文件,一個是指定Grunt庫的相關依賴的package.json
文件,基本配置類似下面的代碼:
{ "name": "my-project-name", "version": "0.1.0", "devDependencies": { "grunt": "~0.4.1", "grunt-contrib-jshint": "~0.6.0", "grunt-contrib-nodeunit": "~0.2.0", "grunt-contrib-uglify": "~0.2.2" } }
還需要一個專門的配置文件Gruntfile
,這個文件可以使用Javascript或CoffeeScript實現,所以具體的文件名可以是Gruntfile.js
或Gruntfile.coffee
。一個典型的配置文件如下所示:
module.exports = function(grunt) { // Project configuration. grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n' }, build: { src: 'src/<%= pkg.name %>.js', dest: 'build/<%= pkg.name %>.min.js' } } }); // 加載包含 "uglify" 任務的插件。 grunt.loadNpmTasks('grunt-contrib-uglify'); // 默認被執行的任務列表。 grunt.registerTask('default', ['uglify']); };
例子中加載了Grunt插件,定義了自定義任務,運行時執行壓縮js源碼的工作並在文件添加一句帶有時間戳的注釋。此外,Grunt還有很強大的編譯時做代碼檢查的功能插件grunt JSHint
,檢測到文件發生變化時就執行編譯壓縮的功能插件grunt watch
,執行JS代碼測試、執行CSS編譯合並等等。
Grunt這個詞的意思是
呼嚕、咕噥
,也表示魔獸爭霸中的獸人步兵
,孔武有力,輕松解決一切困難的任務。還有一個說法是,來源於
Grunt Work
,這個詞的意思是繁重無聊的重復勞動,而Grunt
工具的目標就是消除這些繁瑣任務,把前端程序員的創造力解放出來。
更多信息可以參考官方網站:
http://gruntjs.com/
Bower
Bower是Twitter公司開發的Web包管理工具。它能夠自動安裝我們項目中需要的Javascript依賴庫,檢測各個庫里依賴的其他庫,以及管理各種庫的版本。
安裝非常簡單,執行npm安裝命令即可:
npm install -g bower
使用bower安裝JS庫也非常簡單:
# 安裝jquery bower install jquery # 安裝GitHub里庫,直接可以不寫https://github.com/ bower install desandro/masonry # 也支持Git協議 bower install git://github.com/user/package.git # 當然也可以使用JS文件的URL進行安裝 bower install http://example.com/script.js
例如執行第一個命令安裝jquery,輸出如下信息:
bower jquery#* cached git://github.com/jquery/jquery.git#2.1.3 bower jquery#* validate 2.1.3 against git://github.com/jquery/jquery.git#* bower jquery#~2.1.3 install jquery#2.1.3 jquery#2.1.3 bower_components\jquery
這說明已經安裝成功。此時在本地的bower_components文件夾下,就可以看到jquery的js文件和源代碼。
如果項目里依賴的JS庫比較多,則可以像Grunt一樣的使用配置文件,配置文件名稱叫bower.json
,然后在項目目錄下執行如下命令即可:
bower init
典型的bower.json
文件如下所示:
{ "name": "my-project", "version": "1.0.0", "main": "path/to/main.css", "ignore": [ ".jshintrc", "**/*.txt" ], "dependencies": { "<name>": "<version>", "<name>": "<folder>", "<name>": "<package>" }, "devDependencies": { "<test-framework-name>": "<version>" } }
Bower
這個詞的含義是樹蔭、涼亭
,大樹底下好乘涼,有了它,什么JS的庫依賴都能擺平。這個項目是由F.A.T
和Alex MacCaw
帶領的團隊開發的,於2012年作為Twitter開源工程的一部分。Twitter公司的logo原型是一只拉里鳥,這個項目跟鳥也自然有關系。BowerBird
是園丁鳥科的一種鳥,這種鳥的雄鳥會打造一個涼亭(英文也是Bower),然后用顏色鮮艷的飾物來裝飾它,用以吸引異性。所以這個項目的logo也是一個嘴里銜着一片樹葉的漂亮小鳥,象征着Bower
從JavaScript庫的森林里帶來點點滴滴的依賴庫用以構建自己的體系。
更多的信息請參考官網網站:
http://bower.io/
http-server
我們一般的項目中用到的AppServer或是WebServer一般都比較重量級,我們測試一些前端展示的頁面需要准備很重量級的環境不是很方便。特別是有時候我們的后端和前端是並行開發,編寫前端代碼的時候,后端的數據接口並沒有准備好,也迫切要求我們在前端開發過程中有一個簡單可用、靈活變化,可以快速的啟動、方便修改、隨時可以模擬后台數據的輕量級Server環境。NodeJS里的http-server模塊就是這么一個輕量級的server。同其他工具一樣,我們使用NPM安裝:
npm install -g http-server
顯示以下信息則表示安裝成功:
C:\Program Files\nodejs\http-server -> C:\Program Files\nodejs\node_modules\http-server\bin\http-server C:\Program Files\nodejs\hs -> C:\Program Files\nodejs\node_modules\http-server\bin\http-server http-server@0.7.4 C:\Program Files\nodejs\node_modules\http-server ├── opener@1.4.0 ├── colors@1.0.3 ├── union@0.4.4 (qs@2.3.3) ├── portfinder@0.2.1 (mkdirp@0.0.7) ├── optimist@0.6.1 (wordwrap@0.0.2, minimist@0.0.10) └── ecstatic@0.5.8 (mime@1.2.11, he@0.5.0, minimist@1.1.0)
此時,我們再任意的文件夾新建一個index.html
文件,內容如下:
<html> <body> <H1>hello,http-server!</H1> </body> </html>
然后在此路徑下命令行執行:
http-server
返回如下信息證明已經啟動:
Starting up http-server, serving ./ on: http://0.0.0.0:8080 Hit CTRL-C to stop the server
在瀏覽器中訪問http://localhost:8080
,顯示如下圖:
如果目錄中沒有index.html
文件,則瀏覽器中會列出所有的文件列表:
這個例子說明,我們可以在任意的目錄執行“,使得本目錄變成一個HttpServer的根目錄,可以通過HTTP協議方法目錄中的所有文件,很方便我們測試、調試前端代碼。
Http-server是不是很酷?
跟Apache Http Server或是Microsoft IIS服務器擁有一樣的功能,但是方便得多,簡單得多。當然除了作為HttpServer獨立運行,很多的時候我們也會直接在NodeJS代碼中使用http-server模塊實現更復雜的功能和邏輯,像不像Jetty這種嵌入式的HttpServer?
更多的用法和參數,詳見http-server
的官方網站:
https://github.com/nodeapps/http-server
Karma
Karma是一款用來執行測試用例的工具,由Pivotal Labs
公司開發,在2012年開源、2013年改名為Karma,官方網站首頁為:
http://karma-runner.github.io
Karma最大的特點就是支持在不同平台的多種瀏覽器中運行測試的JavaScript代碼。這個項目的主要目標就是使前端JavaScript的測試驅動開發(Test-Driven Development,TDD)更簡單、更快、更有趣。而且它也做到了這個目標,so cool!
Karma有幾個突出特性:
- 在真實的設備上運行測試用例,設備包括各種手機和平板、甚至是沒有界面的PhantomJS實例;
- 可以從命令行或IDE上遠程控制整個測試流程,只需要保存一個文件,Karma就會自己運行所有的測試用例;
- 可以直接跟Jasmine,Mocha,QUnit等測試框架集成,甚至對任何其他測試框架、你可以簡單實現一個適配器集成到Karma;
- 可以跟Grunt,Gulp等工具集成,使得在開發是方便地進行自動化測試;
- 直接可以在類似WebStorm或Google Chrome之類的工具中方便地調試;
- 可以跟Jenkins,Travis,Semaphore等持續集成工具集成;
對於AngularJS項目,官方推薦使用karma-ng-scenario
插件和Protractor
進行測試。
具體的例子,我們結合下一個測試用例編寫工具Jasmine
一起來看。
Karma的官方首頁上用大字號的英文寫到:“在AngularJS團隊,我們依賴測試,所以我們一直在尋找更好的工具來改善我們的程序人生。這就是為什么我們創造了Karma,這個能滿足我們一切需要的測試用例執行工具的原因”。
Karma這個單詞的意思是
因果報應、因緣
。所謂有其因必有其,這是不是恰恰跟測試的內涵是一致的呢?關於這個項目名字的來歷也很有意思,項目的創立者
Vojta Jina
最開始的時候根據“神奇測試工具(Testing Spectacular
)”的寓意,把這兩個詞合並成一個就成了項目名稱Testacular
。開源以后用的人多了,就有人發現這個詞跟另一個非常有爭議的詞“睾丸(testicular
)”幾乎一樣,這時候就有人建議項目更改一個名字。鹽湖城的網友Ryan Florence
在2013年3月5號在項目的GitHub官方提了一個建議,很快得到了非常多的人參與討論,大部分人支持改名。到了3月8日國際婦女節這天,Jina終於決定項目改名為Karma
。
Jasmine
Jasmine提供了一套類似於Java里的JUnit或Google Truth的語法,使用行為驅動方式來編寫JavaScript單元測試代碼(Behavior-Driven JavaScript)。
Jasmine四個核心概念:分組、用例、期望、匹配,分別對應Jasmine的四種函數:
describe(string,function)
:這個函數表示分組,也就是一組測試用例。類似於JUnit里的一個TestSuite。it(string,function)
:這個函數表示測試用例。類似於JUnit里的TestCase。expect(expression)
:表示期望expression這個表達式具有某個值或者具有某種行為。expect
跟to***
結合成expect(期望值).toXXX(實際值)
,類似JUnit里的Assert.assertXXX(期望值,實際值)
。to***(arg)
:這個函數表示匹配。
典型的測試用例代碼如下:
describe("A suite", function() { it("contains spec with an expectation", function() { expect(true).toBe(true); }); }); describe("A suite is just a function", function() { var a; it("and so is a spec", function() { a = true; expect(a).toBe(true); }); });
在瀏覽器里運行,結果如下:
2 specs, 0 failures A suite contains spec with an expectation A suite is just a function and so is a spec
更多的信息可以參見Jasmine的官方網站:
http://jasmine.github.io/
Jasmine
的含義是茉莉花
,它讓我們可以像茉莉一樣優雅地編寫測試代碼。這個項目誕生於2008年的感恩節,
Pivotal Labs
公司當時需要一款不依賴於DOM和請求-響應周期的JavaScript測試框架,但是市面上沒有可用的,於是Davis W. Frank
決定自己實現。他當時在舊金山的家里開始做這個測試框架,后院里開滿了前任房子主人留下的茉莉花(英文名Jasmine
)。在某個一瞬間,Frank腦子里涌現了一個很久之前就有的思想火花,從最簡潔的JavaScript測試框架這幾個詞出發,就可以聯想到茉莉花:JavaScript Minimal Testing
->JS Minimal Test
->JS Min Test
->Jasmine
。這樣,這個項目就誕生了。
Protractor
Protractor是一款端對端的集成測試工具,專門為AngularJS應用定制的自動化測試工具(End to End Testing for AngularJS)。
Proctactor的原理是利用Web自動化測試框架Selenium的WebDriverJS技術,可以借助於NodeJS直接調用瀏覽器(IE、FF、Chrome)的接口。Jasmine是用來編寫測試,Karma是用來執行測試,Protractor用來模擬用戶操作行為、自動測試。
完整的例子,可以從Github clone到本地查看:
git clone http://juliemr.github.io/protractor-demo
克隆protractor-demo
代碼以后,可以看到一個典型的Web自動測試代碼如下:
// test/spec.js describe('angularjs homepage', function() { it('should add numbers', function() { element(by.model('first')).sendKeys(4); element(by.model('second')).sendKeys(5); element(by.id('gobutton')).click(); expect(element(by.binding('latest')).getText()). toEqual('9'); }); });
例子里先打開一個瀏覽器,運行示例網頁,然后自動在兩個文本框分別模擬輸入4和5,然后模擬點擊一下按鈕,最后判斷輸出結果文本是不是9。怎么樣,很簡單吧。
執行測試也很簡單,在項目目錄打開兩個命令行,第一個命令行執行下面兩個命令:
npm install
npm start
另一個命令行,執行:
npm test
效果如下:
最后可以看到測試結果:
Finished in 11.587 seconds 3 tests, 5 assertions, 0 failures
更多信息參見官方網站地址:
https://github.com/angular/protractor
詳細的使用文檔參見:
https://github.com/angular/protractor/tree/master/docs
WebDriverJs可以參見:
https://code.google.com/p/selenium/wiki/WebDriverJs
Protractor
這個英文單詞的含義是量角器
,用於精確的度量我們的AngularJS項目。而且官方還有一個說法:量角器(Protractor
)是用來測量角度(Angles
)的,而本項目Protractor
是用來測試AngularJS
的(注意Angles
和AngularJS
比較相似)。
項目結構
本章的最后我們來看一下整合好的前端開發環境結構。一個典型的目錄如下圖所示:
常用的目錄項,整理如下:
|-.git //git使用的文件夾 |-package.json //npm配置文件 |-bower.json //bower配置文件 |-Gruntfile.js //Grunt配置文件 |-app //web應用的前端代碼 |-bower_components //bower依賴庫,不需要加入到git倉庫 |-js |-img |-css |- ... ... |-node_modules //npm依賴庫,不需要加入到git倉庫 |-scripts //項目常用的shell腳本 |-test //前端JavaScript test代碼 |-protractor-conf.js //protractor配置文件 |-karma.conf.js //karma配置文件 |-e2e //交互場景測試代碼 |-unit //單元測試代碼
具體的項目里,可以根據自己的需求選擇合適的幾款技術框架和開發工具,不需要全部的東西都用上。