AngularJS是什么
AngularJS的官方文檔這樣介紹它:
完全使用JavaScript編寫的客戶端技術(shù)。同其它歷史悠久的Web技術(shù)(HTML、CSS、JavaScript)配合使用,使Web應(yīng)用開發(fā)比以往更簡(jiǎn)單、更快捷。
AngularJS的開發(fā)團(tuán)隊(duì)將其描述為一種構(gòu)建動(dòng)態(tài)Web應(yīng)用的結(jié)構(gòu)化框架。AngularJS主要用于構(gòu)建單頁面Web應(yīng)用。
??AngularJS通過原生的Model-View-Controller
(MVC,模型-視圖-控制器)功能增強(qiáng)了HTML。利用它可以將頁面的一部分內(nèi)容封裝成一個(gè)應(yīng)用,并且不強(qiáng)迫整個(gè)頁面都使用AngularJS進(jìn)行開發(fā)。
MVC(模型 視圖 控制器)
MVC背后的核心理念就是,你在你的代碼之間明確分離管理數(shù)據(jù)(模型)、應(yīng)用程序邏輯(控制器)、并將數(shù)據(jù)給用戶(視圖)。
??在AngularJS應(yīng)用中,視圖層就是DOM,控制器就是JavaScript類,模型數(shù)據(jù)存儲(chǔ)在對(duì)象屬性中。
??視圖從模型中獲取數(shù)據(jù)展示給用戶。當(dāng)用戶通過點(diǎn)擊或者輸入和應(yīng)用程序進(jìn)行交互時(shí),控制器通過改變模型中的數(shù)據(jù)響應(yīng)。最終,模型層通知視圖層,已經(jīng)發(fā)生改變,更新顯示。
數(shù)據(jù)綁定
Hello World
第一個(gè)AngularJS例子
<body ng-app>
<input type="text" ng-model="name">
<h1>{{ name }}</h1>
</body>
運(yùn)行效果:
AngularJS中的數(shù)據(jù)綁定
要實(shí)現(xiàn)AngularJS的功能,只要在頁面中引入angular.js
,并在某個(gè)DOM元素上明確設(shè)置ng-app
屬性即可。ng-app
屬性聲明所有被其包含的內(nèi)容都屬于這個(gè)angularJS應(yīng)用。只有被具有ng-app
屬性的DOM元素包含的元素才會(huì)受AngularJS影響。
AngularJS會(huì)記錄數(shù)據(jù)模型所包含的數(shù)據(jù)在任何特定時(shí)間點(diǎn)的值,而不是原始值。當(dāng)AngularJS認(rèn)為某個(gè)值可能發(fā)生變化時(shí),它會(huì)運(yùn)行自己的事件循環(huán)來檢查這個(gè)值是否變“臟”。如果該值從上次事件循環(huán)運(yùn)行之后發(fā)生了變化,則該值被認(rèn)為是“臟”值。這個(gè)過程被稱作臟檢查。臟檢查是檢查數(shù)據(jù)模型變化的有效手段。當(dāng)有潛在的變化存在時(shí),AngularJS會(huì)在事件循環(huán)時(shí)執(zhí)行臟檢查來保證數(shù)據(jù)的一致性。
模塊
在AngularJS中,模塊是定義應(yīng)用的最主要方式。模塊包含了主要的應(yīng)用代碼。一個(gè)應(yīng)用可以包含多個(gè)模塊,每一個(gè)模塊都包含了定義具體功能的代碼。
我們使用angular.module()
方法來聲明模塊,這個(gè)方法接受兩個(gè)參數(shù),第一個(gè)是模塊的名稱,第二個(gè)是依賴列表,也就是可以被注入到模塊中的對(duì)象列表。
angular.module('myApp', []);
//這個(gè)方法相當(dāng)于AngularJS模塊的setter方法,是用來定義模塊的。
調(diào)用這個(gè)方法時(shí)如果只傳遞一個(gè)參數(shù),就可以用它來引用模塊。
// 這個(gè)方法用于獲取應(yīng)用
angular.module(' myApp ')
//這個(gè)方法相當(dāng)于AngularJS模塊的getter方法,用來獲取對(duì)模塊的引用。
接下來,就可以在angular.module('myApp')
返回的對(duì)象上創(chuàng)建應(yīng)用了。
參數(shù)
下面是angular.module()
的參數(shù)列表。
- name(字符串):
name
是模塊的名稱,字符串變量。 - requires(字符串?dāng)?shù)組):
requires
包含了一個(gè)字符串變量組成的列表,每個(gè)元素都是一個(gè)模塊名稱,本模塊依賴于這些模塊,依賴需要在本模塊加載之前由注入器進(jìn)行預(yù)加載。
作用域
應(yīng)用的作用域是和應(yīng)用的數(shù)據(jù)模型相關(guān)聯(lián)的,同時(shí)作用域也是表達(dá)式執(zhí)行的上下文。$scope
對(duì)象是定義應(yīng)用業(yè)務(wù)邏輯、控制器方法和視圖屬性的地方。
在應(yīng)用將視圖渲染并呈獻(xiàn)給用戶之前,視圖中的模板會(huì)和作用域進(jìn)行連接,然后應(yīng)用會(huì)對(duì)DOM進(jìn)行設(shè)置以便將屬性變化通知給AngularJS。
作用域是應(yīng)用狀態(tài)的基礎(chǔ)。基于動(dòng)態(tài)綁定,我們可以依賴視圖在修改數(shù)據(jù)時(shí)立刻更新$scope
,也可以依賴$scope
在其發(fā)生變化時(shí)立刻重新渲染視圖。
AngularJS將$scope
設(shè)計(jì)成和DOM類似的結(jié)構(gòu),因此$scope
可以進(jìn)行嵌套,也就是說我們可以引用父級(jí)$scope
中的屬性。
作用域提供了監(jiān)視數(shù)據(jù)模型變化的能力。它允許開發(fā)者使用其中的apply
機(jī)制,將數(shù)據(jù)模型的變化在整個(gè)應(yīng)用范圍內(nèi)進(jìn)行通知。我們?cè)谧饔糜虻纳舷挛闹卸x和執(zhí)行表達(dá)式,同時(shí)它也是將事件通知給另一個(gè)控制器和應(yīng)用其他部分的中介。
視圖和$scope
AngularJS啟動(dòng)并生成視圖時(shí),會(huì)將根ng-app
元素同$rootScope
進(jìn)行綁定。$rootScope
是所有$scope
對(duì)象的最上層。
$rootScope
是AngularJS中最接近全局作用域的對(duì)象。在$rootScope
上附加太多業(yè)務(wù)邏并不是好主意,這與污染JS的全局作用域是一樣的。
$scope
對(duì)象就是一個(gè)普通的JS對(duì)象,我們可以在其上隨意修改或添加屬性。
$scope
對(duì)象充當(dāng)數(shù)據(jù)模型,$scope
并不負(fù)責(zé)處理和操作數(shù)據(jù),它只是視圖和HTML之間的橋梁。
$scope
的所有屬性,都可以自動(dòng)被視圖訪問到。假設(shè)我們有如下的代碼:
<div ng-app="myApp">
<h1>Hello {{name}}</h1>
</div>
我們希望{{name}}
變量是本地$scope
的一個(gè)屬性。
angular.module('myApp', []).run(function($rootScope) {
$rootScope.name = "World";
});
我們可以在AngularJS應(yīng)用的模板中使用多種標(biāo)記,包括下面這些:
- 指令:將DOM元素增強(qiáng)為可復(fù)用的DOM組件的屬性或元素
- 值綁定:模板語法
{{ }}
可以將表達(dá)式綁定到視圖上 - 過濾器:可以在視圖中使用的函數(shù),用來進(jìn)行格式化
- 表單控件:用來檢驗(yàn)用戶輸入的控件
作用域能做什么
作用域有以下的基本功能:
- 提供觀察者以監(jiān)視數(shù)據(jù)模型的變化
- 可以將數(shù)據(jù)模型的變化通知給整個(gè)應(yīng)用,甚至是系統(tǒng)外的組件
- 可以進(jìn)行嵌套,隔離業(yè)務(wù)功能和數(shù)據(jù)
- 給表達(dá)式提供運(yùn)算時(shí)所需的執(zhí)行環(huán)境
作用域包含了渲染視圖時(shí)所需的功能和數(shù)據(jù),它是所有視圖的唯一源頭。可以將作用域理解成視圖模型(view model
)。
angular.module('myApp', []).run(function($rootScope) {
$rootScope.name = "World";
});
<div ng-app="myApp">
<h1>Hello {{ name }}</h1>
</div>
我們可以不將變量設(shè)置在$rootScope
上,而是用控制器顯式創(chuàng)建一個(gè)隔離的子$scope
對(duì)象,把它設(shè)置到這個(gè)子對(duì)象上。使用ng-controller
指令可以將一個(gè)控制器對(duì)象附加到DOM元素上,如下所示:
<div ng-app="myApp">
<div ng-controller="MyController">
<h1>Hello {{ name }}</h1>
</div>
</div>
可以創(chuàng)建一個(gè)控制器來管理與其相關(guān)的變量,而不用將name
變量直接放在$rootScope
上。
angular.module("myApp",[]).controller('MyController',function($scope) {
$scope.name = "Ari";
});
ng-controller
指令為這個(gè)DOM元素創(chuàng)建了一個(gè)新的$scope
對(duì)象,并將它嵌套在$rootScope
中。
$scope的生命周期
當(dāng)AngularJS關(guān)心的事件發(fā)生在瀏覽器中時(shí),比如用戶在通過ng-model
屬性監(jiān)控的輸入字段中輸入,或者帶有ng-click
屬性的按鈕被點(diǎn)擊時(shí),AngularJS的事件循環(huán)都會(huì)啟動(dòng)。這個(gè)事件將在AngularJS執(zhí)行上下文中處理。
每當(dāng)事件被處理時(shí),$scope
就會(huì)對(duì)定義的表達(dá)式求值。此時(shí)事件循環(huán)會(huì)啟動(dòng),并且AngularJS應(yīng)用會(huì)監(jiān)控應(yīng)用程序內(nèi)的所有對(duì)象,臟值檢測(cè)循環(huán)也會(huì)運(yùn)行。
$scope
對(duì)象的生命周期處理有四個(gè)不同階段。
- 創(chuàng)建
在創(chuàng)建控制器或指令時(shí),AngularJS會(huì)用$injector
創(chuàng)建一個(gè)新的作用域,并在這個(gè)新建的控制器或指令運(yùn)行時(shí)將作用域傳遞進(jìn)去。 - 鏈接
當(dāng)AngularJS開始運(yùn)行時(shí),所有的$scope
對(duì)象都會(huì)附加或者鏈接到視圖中。所有創(chuàng)建$scope
對(duì)象的函數(shù)也會(huì)將自身附加到視圖中。這些作用域?qū)?huì)注冊(cè)當(dāng)AngularJS應(yīng)用上下文中發(fā)生變化時(shí)需要運(yùn)行的函數(shù)。這些函數(shù)被稱為$watch
函數(shù),AngularJS通過這些函數(shù)獲知何時(shí)啟動(dòng)事件循環(huán)。 - 更新
當(dāng)事件循環(huán)運(yùn)行時(shí),它通常執(zhí)行在頂層$scope
對(duì)象上(被稱作$rootScope
),每個(gè)子作用域都執(zhí)行自己的臟值檢測(cè)。每個(gè)監(jiān)控函數(shù)都會(huì)檢查變化。如果檢測(cè)到任意變化,$scope
對(duì)象就會(huì)觸發(fā)指定的回調(diào)函數(shù)。 - 銷毀
當(dāng)一個(gè)$scope
在視圖中不再需要時(shí),這個(gè)作用域?qū)?huì)清理和銷毀自己。
盡管永遠(yuǎn)不會(huì)需要清理作用域(因?yàn)锳ngularJS會(huì)為你處理),但是知道是誰創(chuàng)建了這個(gè)作用域還是有用的,因?yàn)槟憧梢允褂眠@個(gè)$scope
上叫做$destory()
的方法來清理這個(gè)作用域。
指令和作用域
指令通常不會(huì)創(chuàng)建自己的$scope
,但也有例外。比如ng-controller
和ng-repeat
指令會(huì)創(chuàng)建自己的子作用域并將它們附加到DOM元素上。
控制器
控制器的作用是增強(qiáng)視圖。在AngularJS中的控制器是一個(gè)函數(shù),用來向視圖的作用域中添加額外的功能。我們用它來給作用域?qū)ο笤O(shè)置初始狀態(tài),并添加自定義行為。
當(dāng)我們?cè)陧撁嫔蟿?chuàng)建一個(gè)新的控制器時(shí),AngularJS會(huì)生成并傳遞一個(gè)新$scope
給這個(gè)控制器。可以在這個(gè)控制器里初始化$scope
。由于AngularJS會(huì)負(fù)責(zé)處理控制器的實(shí)例化過程,我們只需編寫構(gòu)造函數(shù)即可。
function FirstController($scope) {
$scope.message = "hello";
}
我們是在全局作用域中創(chuàng)建的這個(gè)函數(shù)。這樣做并不合適,因?yàn)闀?huì)污染全局命名空間。更合理的方式是創(chuàng)建一個(gè)模塊,然后在模塊中創(chuàng)建控制器。
var app = angular.module('app', []);
app.controller('FirstController', function($scope) {
$scope.message = "hello";
});
只需創(chuàng)建控制器作用域中的函數(shù),就能創(chuàng)建可以在視圖中使用的自定義操作。我們可以在視圖中像調(diào)用普通數(shù)據(jù)一樣調(diào)用$scope
上的函數(shù)。
用內(nèi)置指令ng-click
可以將按鈕、鏈接等其他任何DOM元素同點(diǎn)擊事件進(jìn)行綁定。ng-click
指令將瀏覽器中的mouseup
事件,同設(shè)置在DOM元素上的事件處理程序綁定在一起。
<div ng-controller="FirstController">
<button ng-click="add(1)" class="btn">Add</button>
<a ng-click="subtract(1)" class="btn btn-default">Subtract</a>
<h4>Current count: {{counter}}</h4>
</div>
按鈕和鏈接都被綁定在了內(nèi)部$scope
的一個(gè)操作上,當(dāng)點(diǎn)擊任何一個(gè)元素時(shí)AngularJS都會(huì)調(diào)用相應(yīng)的方法。下面給FirstController
添加一個(gè)操作:
app.controller('FirstController', function($scope) {
$scope.counter = 0;
$scope.add = function(amount) { $scope.counter += amount; };
$scope.subtract = function(amount) { $scope.counter -= amount; };
});
用這種設(shè)置方式我們可以在視圖中調(diào)用add()
或subtract()
方法,這兩個(gè)方法可以定義在FirstController
的作用域中,或其父級(jí)的$scope
中。
控制器可以將與一個(gè)獨(dú)立視圖相關(guān)的業(yè)務(wù)邏輯封裝在一個(gè)獨(dú)立的容器中。
控制器并不適合用來執(zhí)行DOM操作、格式化或數(shù)據(jù)操作,以及除存儲(chǔ)數(shù)據(jù)模型之外的狀態(tài)維護(hù)操作。它只是視圖和$scope
之間的橋梁。
AngularJS允許在$scope
上設(shè)置包括對(duì)象在內(nèi)的任何類型的數(shù)據(jù),并且在視圖中還可以展示對(duì)象的屬性。
app.controller('MyController', function($scope) {
$scope.person = {
name: 'Ari Lerner'
};
});
在擁有ng-controller='MyController'
這個(gè)屬性的元素內(nèi)部的任何子元素中,都可以訪問person
對(duì)象,因?yàn)樗嵌x在$scope
上的。
<div ng-app="myApp">
<div ng-controller="MyController">
<h1>{{ person }}</h1>
and their name:
<h2>{{ person.name }}</h2>
</div>
</div>
效果如圖:
正如看到的這樣,
$scope
對(duì)象用來從數(shù)據(jù)模型向視圖傳遞信息。同時(shí),它也可以用來設(shè)置事件監(jiān)聽器,同應(yīng)用的其他部分進(jìn)行交互,以及創(chuàng)建與應(yīng)用相關(guān)的特定業(yè)務(wù)邏輯。
控制器嵌套(作用域包含作用域)
AngularJS應(yīng)用的任何一個(gè)部分,無論它渲染在哪個(gè)上下文中,都有父級(jí)作用域存在。對(duì)于ng-app
所處的層級(jí)來講,它的父級(jí)作用域就是$rootScope
。有一個(gè)例外:在指令內(nèi)部創(chuàng)建的作用域被稱作孤立作用域。除了孤立作用域外,所有的作用域都通過原型繼承而來,也就是說它們都可以訪問父級(jí)作用域。
默認(rèn)情況下,AngularJS在當(dāng)前作用域中無法找到某個(gè)屬性時(shí),便會(huì)在父級(jí)作用域中進(jìn)行查找。如果AngularJS找不到對(duì)應(yīng)的屬性,會(huì)順著父級(jí)作用域一直向上尋找,直到抵達(dá)$rootScope
為止。如果在$rootScope
中也找不到,程序會(huì)繼續(xù)運(yùn)行,但視圖無法更新。
app.controller('ParentController', function($scope) {
$scope.person = {greeted: false};
});
app.controller('ChildController', function($scope) {
$scope.sayHello = function() {
$scope.person.name = 'Ari Lerner';
};
});
如果我們將ChildController
置于ParentController
內(nèi)部,那ChildController
的$scope
對(duì)象的父級(jí)作用域就是ParentController
的$scope
對(duì)象。根據(jù)原型繼承的機(jī)制,我們可以在子作用域中訪問ParentController
的$scope
對(duì)象。
<div ng-controller="ParentController">
<div ng-controller="ChildController">
<a ng-click="sayHello()">Say hello</a>
</div>
{{ person }}
</div>
效果如圖:
控制器應(yīng)該盡可能保持短小精悍,而在控制器中進(jìn)行DOM操作和數(shù)據(jù)操作則是一個(gè)不好的實(shí)踐。
angular.module('myApp',[]).controller('MyController', function($scope) {
$scope.shouldShowLogin = true;
$scope.showLogin = function () {
$scope.shouldShowLogin = !$scope.shouldShowLogin;
};
$scope.clickButton = function() {
$('#btn span').html('Clicked');
};
$scope.onLogin = function(user) {
$http({
method: 'POST',
url: '/login',
data: {
user: user
}
}).success(function(data) {
// user
});
};
});
設(shè)計(jì)良好的應(yīng)用會(huì)將復(fù)雜的邏輯放到指令和服務(wù)中。通過使用指令和服務(wù),我們可以將控制器重構(gòu)成一個(gè)輕量且更易維護(hù)的形式。
angular.module('myApp',[]).controller('MyController',function($scope,UserSrv) {
// 內(nèi)容可以被指令控制
$scope.onLogin = function(user) {
UserSrv.runLogin(user);
};
});
表達(dá)式
用{{ }}
符號(hào)將一個(gè)變量綁定到$scope
上的寫法本質(zhì)上就是一個(gè)表達(dá)式:{{expression}}
。當(dāng)用$watch
進(jìn)行監(jiān)聽時(shí),AngularJS會(huì)對(duì)表達(dá)式或函數(shù)進(jìn)行運(yùn)算。
表達(dá)式和eval(js)
非常相似,但是由于表達(dá)式由AngularJS來處理,它們有以下顯著不同的特性:
- 所有的表達(dá)式都在其所屬的作用域內(nèi)部執(zhí)行,并有訪問本地
$scope
的權(quán)限 - 如果表達(dá)式發(fā)生了
TypeError
和ReferenceError
并不會(huì)拋出異常 - 不允許使用任何流程控制功能(例如
if/else
) - 可以接受過濾器和過濾器鏈
對(duì)表達(dá)式進(jìn)行的任何操作,都會(huì)在其所屬的作用域內(nèi)部執(zhí)行,因此可以在表達(dá)式內(nèi)部調(diào)用那些限制在此作用域內(nèi)的變量,并進(jìn)行循環(huán)、函數(shù)調(diào)用、將變量應(yīng)用到數(shù)學(xué)表達(dá)式中等操作。
解析AngularJS表達(dá)式
盡管AngularJS會(huì)在運(yùn)行$digest
循環(huán)的過程中自動(dòng)解析表達(dá)式,但有時(shí)手動(dòng)解析表達(dá)式也是非常有用的。AngularJS通過$parse
這個(gè)內(nèi)部服務(wù)來進(jìn)行表達(dá)式的運(yùn)算,這個(gè)服務(wù)能夠訪問當(dāng)前所處的作用域。這個(gè)過程允許我們?cè)L問定義在$scope
上的原始JS數(shù)據(jù)和函數(shù)。
將$parse
服務(wù)注入到控制器中,然后調(diào)用它就可以實(shí)現(xiàn)手動(dòng)解析表達(dá)式。```
<div ng-controller="MyController">
<input ng-model="expr" type="text" placeholder="Enter an expression" />
<h2>{{ parseValue }}</h2>
</div>
angular.module("myApp", [])
.controller('MyController',function ($scope,$parse) {
$scope.$watch('expr',function (newVal,oldVal,scope) {
if (newVal !==oldVal) {
// 用該表達(dá)式設(shè)置parseFun
var parseFun = $parse(newVal);
// 獲取經(jīng)過解析后表達(dá)式的值
$scope.parsedValue = parseFun(scope);
}
})
})
插值字符串
在AngularJS中,我們的確有手動(dòng)運(yùn)行模板編譯的能力。例如,插值允許基于作用域上的某個(gè)條件實(shí)時(shí)更新文本字符串。要在字符串模板中做插值操作,需要在對(duì)象中注入$interpolate
服務(wù)。
angular.module('myApp',[])
.controller('MyController',function($scope,$interpolate) {
// 我們同時(shí)擁有訪問$scope和$interpolate服務(wù)的權(quán)限
});
$interpolate
服務(wù)是一個(gè)可以接受三個(gè)參數(shù)的函數(shù),其中第一個(gè)參數(shù)是必需的。
- text(字符串):一個(gè)包含字符插值標(biāo)記的字符串。
- mustHaveExpression(布爾型):如果將這個(gè)參數(shù)設(shè)為
true
,當(dāng)傳入的字符串中不含有表達(dá)式時(shí)會(huì)返回null
。 - trustedContext(字符串):AngularJS會(huì)對(duì)已經(jīng)進(jìn)行過字符插值操作的字符串通過
$sec.getTrusted()
方法進(jìn)行嚴(yán)格的上下文轉(zhuǎn)義。
$interpolate
服務(wù)返回一個(gè)函數(shù),用來在特定的上下文中運(yùn)算表達(dá)式。
設(shè)置好這些參數(shù)后,就可以在控制器中進(jìn)行字符插值的操作了。例如,假設(shè)我們希望可以在電子郵件的正文中進(jìn)行實(shí)時(shí)編輯,當(dāng)文本發(fā)生變化時(shí)進(jìn)行字符插值操作并將結(jié)果展示出來。
<div ng-controller="MyController">
<input ng-model="to" type="email" placeholder="Recipient" />
<textarea ng-model="emailBody"></textarea>
<pre>{{ previewText }}</pre>
</div>
由于控制器內(nèi)部設(shè)置了一個(gè)需要每次變化都重新進(jìn)行字符插值的自定義輸入字段,因此需要設(shè)置一個(gè)$watch
來監(jiān)聽數(shù)據(jù)的變化。$watch
函數(shù)會(huì)監(jiān)視$scope
上的某個(gè)屬性。只要屬性發(fā)生變化就會(huì)調(diào)用對(duì)應(yīng)的函數(shù)。可以使用$watch
函數(shù)在$scope
上某個(gè)屬性發(fā)生變化時(shí)直接運(yùn)行一個(gè)自定義函數(shù)。
angular.module('myApp',[])
.controller('MyController', function($scope, $interpolate) {
// 設(shè)置監(jiān)聽
$scope.$watch('emailBody', function(body) {
if (body) {
var template = $interpolate(body);
$scope.previewText =template({to: $scope.to});
}
};
});
現(xiàn)在,在{{previewText}}
內(nèi)部的文本中可以將{{to}}
當(dāng)做一個(gè)變量來使用,并對(duì)文本的變化進(jìn)行實(shí)時(shí)更新。如果需要在文本中使用不同于{{ }}
的符號(hào)來標(biāo)識(shí)表達(dá)式的開始和結(jié)束,可以在$inter polateProvider
中配置。
用startSymbol()
方法可以修改標(biāo)識(shí)開始的符號(hào)。這個(gè)方法接受一個(gè)參數(shù)。
- value(字符型):開始符號(hào)的值。
用endSymbol()
方法可以修改標(biāo)識(shí)結(jié)束的符號(hào)。這個(gè)方法也接受一個(gè)參數(shù)。
- value(字符型): 結(jié)束符號(hào)的值。
如果要修改這兩個(gè)符號(hào)的設(shè)置,需要在創(chuàng)建新模塊時(shí)將$interpolateProvider
注入進(jìn)去。
下面我們來創(chuàng)建一個(gè)服務(wù):
angular.module('emailParser',[])
.config(['$interpolateProvider', function($interpolateProvider) {
$interpolateProvider.startSymbol('__');
$interpolateProvider.endSymbol('__');
}])
.factory('EmailParser', ['$interpolate', function($interpolate) {
// 處理解析的服務(wù)
return {
parse: function(text, context) {
var template = $interpolate(text);
return template(context);
}
};
}]);
現(xiàn)在,我們已經(jīng)創(chuàng)建了一個(gè)模塊,可以將它注入到應(yīng)用中,并在郵件正文的文本中運(yùn)行這個(gè)郵件解析器:
angular.module('myApp',['emailParser'])
.controller('MyController', ['$scope', 'EmailParser',function($scope, EmailParser) {
// 設(shè)置監(jiān)聽
$scope.$watch('emailBody', function(body) {
if (body) {
$scope.previewText = EmailParser.parse(body, {
to: $scope.to
});
}
});
}]);
由于我們將表達(dá)式開始和結(jié)束的符號(hào)都設(shè)置成了__
,因此需要將HTML修改成用這個(gè)符號(hào)取代{{ }}
的版本。
完整代碼:
<body ng-app="myApp">
<div id="emailEditor" ng-controller="MyController">
<input ng-model="to" type="email" placeholder="Recipient" />
<textarea ng-model="emailBody"></textarea>
<div id="emailPreview">
<pre>__ previewText __</pre>
</div>
</div>
<script>
angular.module('myApp', ['emailParser'])
.controller('MyController',
['$scope', 'EmailParser',function($scope, EmailParser) {
$scope.to = 'ari@fullstack.io';
$scope.emailBody = 'Hello __to__';
// Set up a watch
$scope.$watch('emailBody', function(body) {
if (body) {
$scope.previewText =EmailParser.parse(body, {
to: $scope.to
});
}
});
}]);
angular.module('emailParser', [])
.config(['$interpolateProvider',
function($interpolateProvider) {
interpolateProvider.startSymbol('__');
$interpolateProvider.endSymbol('__');
}])
.factory('EmailParser', ['$interpolate',
function($interpolate) {
// a service to handle parsing
return {
parse: function(text, context) {
var template = $interpolate(text);
return template(context);
}
};
}]);
</script>
</body>