## AngularJS是什么? ##
AngularJS是一個前端JavaScript框架,背后有Google支持。這個框架最早是09年發布的,隨后發展迅速,尤其是最近,流行度很高。和其他框架不同,AngularJS有很多獨特的特性,使得其非常與眾不同。考慮到本人的文章多寫的邏輯混亂,如果你對AngularJS不了解,推薦你先去其[官網](http://www.angularjs.org)看看。對於我來說,最吸引我的兩個特性是雙向綁定以及依賴注入。前者免去了開發時顯示的刷新DOM,能讓開發者更專注在邏輯上,而后者則使得測試以及集成變得非常方便。
### Hello,World ###
先來看一個經典的Hello World。
<html> <head> <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.js"></script> <script> function HelloController($scope) { $scope.person = { name: "World" } $scope.sayHelloWorld = function() { alert($scope.person.name); } </script> </head> <body ng-app> <div ng-controller="HelloController"> <input type="text" ng-model="person.name" /> <button ng-click="sayHelloWorld()"></button> </div> </body> </html>
### Controller ###
在Angular中,Controller主要負責初始化scope,包括數據以及所需要的函數。上面的HelloController就是個典型的Controller,另外一種更加強大的定義方式允許你聲明所依賴的模塊。
var controllers = angular.module('demo.controllers'); controllers.controller("demoController", ['$scope', '$http', function($scope, $http) { $scope.test_data = { value: 'test data' }; $scope.test_function = function() { alert("test function"); }; }]);
Controller比較直觀,需要注意的有兩個地方,一是使用$watch關注某個表達式的值,當發生變化時做相應操作,二是使用外部庫操作數據,需要使用apply通知angular,不然的話很有可能外部庫更新了數據,但angular卻沒有做相應更新。
### Directive ###
在前端開發中,經常需要操作DOM,而且有時候需要使用一大堆HTML來構建一個常用的組件,例如Google+信息流中的一條信息,在Angular中這都屬於Directive的作用,這也就意味着在Controller中操作DOM是個錯誤的做法。
通常情況下,Directive定義時采用CamelCase規則進行命名,而在使用時則使用橫線進行分隔。
Directive的定義
var directives = angular.module('demo.directives', []); directives.directive('customDirective', function() { return { restrict: 'ECMA', template: '<nav></nav>', templateUrl: 'directive.html', replace: false, priority: 0, transclude: false, scope: false, terminal: false, require: false, controller: function(scope, element, attrs, transclude, otherInjectables {}, compile: function(element, attrs, transclude) { return { pre: function preLink(scope, element, attrs, controller) {}, post: function postLink(scope, element, attrs, controller) {} }; }, link: function(scope, element, attrs) { } }; });
restrict: 指定了directive的使用形式,共有四種:
1. Element(restrict定義時的E)
2. Attribute(restrict定義時的A)
3. Class(restrict定義時的C)
4. Comment(restrict定義時的M)
compile:在directive中如果需要對DOM元素進行處理,基本都是在這個函數中進行。仔細看這個函數,compile並不能訪問scope,
link:此函數的主要作用就是對DOM和scope做數據綁定。和compile不同,在這個函數中,已經可以訪問scope了。
template和templateUrl:用於指定directive對應的模板,前者直接使用字符串定義模板,而后者則通過url鏈接外部模板文件。在模板中可以使用對應controller或者rootScope中的scope,當然也有例外,具體請看關於scope的解釋。
replace:指定是否使用模板替換directive作用的DOM元素。
priority:指定優先級,angular在處理directive時,會將頁面出現的所有directive按優先級排序,一般這個數值都是不指定的。
controller:directive對應的controller,通常用於directive之間的通信。在這個函數中,所有綁定到this上的變量,其他的directive都能通過使用require來進行訪問。
require:通過指定某個directive的名字,來訪問其對應的controller。其中以?作為前綴時,如果找不到此directive將報錯,而以^為前綴,將會在父元素進行遞歸查找,可以使用數組來引入多個directive,如['directive1','directive2','directive3']
scope:用於指定當前directive所對應的scope,不同的取值之間的影響非常大。
1. false:此時directive與父元素共享scope
2. true:此時directive有自己的scope,該scope繼承父元素所對應的scope
3. isolate:directive有自己的scope,該scope不會繼承自父元素對應的scope,但是仍然可以通過scope.$parent訪問父節點的scope。這不是一個推薦的做法,因為這樣就對父元素進行了限制,影響了directive的使用范圍。如果想在父子元素之間共享數據,可以明確指定那些元素需要父子之間共享。方法共有三種:
使用@將父級scope中的屬性綁定到本地scope中,單向綁定,這個值總是字符串,在template中需要使用{{}}
使用=同上,只不過這里是雙向綁定,在template中可以直接給出父級scope的屬性名稱
使用&用於倒入函數或者表達式
transclude:用於控制是否要將該directive的子元素添加到模板中ng-tranclude指定的元素之下
### Service ###
在Angular中,Service是一些提供常見功能的單例對象。諸如上面出現$http等,其使用也是比較簡單的,只要在使用時聲明這個依賴就可以了,例如上面的demoController。其定義方式主要有一下幾種:
1. service只是簡單的數值可以使用constant(name,value)進行注冊,如果時已經存在的對象,可以使用value(name,value)進行注冊
var services = angular.moudle('demo.services', []); services.constant('number', 42); services.constant('string', 'string'); var existingService = { notify: function(msg) { alert(msg); } }; services.value('notify', existingService);
2. 注冊一個service構造函數
services.service('demoService2', function() { this.func = function() { }; });
3. 注冊一個工廠函數用於創建service實例,這種方式可以在創建服務實例之前做些處理
services.factory('demoService1', function(msg) { // some processing code return { func: function() { } }; });
4. 使用provider,使用這種方式,復雜一點,但是好處是可以對service進行配置。
services.provider('demoService3', function() { this.value = "string"; this.$get = function() { var value = this.value; return { print: function() { console.log(value); } } } this.setValue = function(value) { this.value = value; } });
// 使用config可以對provider進行配置
services.config(function(demoService3Provider) { demoServiceProder.setValue('hello'); });
當然,創建服務也是可以聲明依賴的,具體格式和controller類似,不再羅嗦。
Angular還所有很多概念,包括router和filter等,我很少用到,沒有細研究過。