AngularJS是什么
AngularJS的官方文檔這樣介紹它:
完全使用JavaScript編寫的客戶端技術(shù)颈渊。同其它歷史悠久的Web技術(shù)(HTML夹界、CSS赌莺、JavaScript)配合使用窖逗,使Web應(yīng)用開發(fā)比以往更簡單累奈、更快捷斥铺。
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ù)存儲在對象屬性中。
??視圖從模型中獲取數(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元素包含的元素才會受AngularJS影響。
AngularJS會記錄數(shù)據(jù)模型所包含的數(shù)據(jù)在任何特定時(shí)間點(diǎn)的值效览,而不是原始值些膨。當(dāng)AngularJS認(rèn)為某個(gè)值可能發(fā)生變化時(shí),它會運(yùn)行自己的事件循環(huán)來檢查這個(gè)值是否變“臟”钦铺。如果該值從上次事件循環(huán)運(yùn)行之后發(fā)生了變化,則該值被認(rèn)為是“臟”值肢预。這個(gè)過程被稱作臟檢查矛洞。臟檢查是檢查數(shù)據(jù)模型變化的有效手段。當(dāng)有潛在的變化存在時(shí),AngularJS會在事件循環(huán)時(shí)執(zhí)行臟檢查來保證數(shù)據(jù)的一致性沼本。
模塊
在AngularJS中噩峦,模塊是定義應(yīng)用的最主要方式。模塊包含了主要的應(yīng)用代碼抽兆。一個(gè)應(yīng)用可以包含多個(gè)模塊识补,每一個(gè)模塊都包含了定義具體功能的代碼。
我們使用angular.module()
方法來聲明模塊辫红,這個(gè)方法接受兩個(gè)參數(shù)凭涂,第一個(gè)是模塊的名稱,第二個(gè)是依賴列表贴妻,也就是可以被注入到模塊中的對象列表切油。
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方法娩鹉,用來獲取對模塊的引用攻谁。
接下來,就可以在angular.module('myApp')
返回的對象上創(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
對象是定義應(yīng)用業(yè)務(wù)邏輯骚灸、控制器方法和視圖屬性的地方。
在應(yīng)用將視圖渲染并呈獻(xiàn)給用戶之前慌植,視圖中的模板會和作用域進(jìn)行連接甚牲,然后應(yīng)用會對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)行嵌套,也就是說我們可以引用父級$scope
中的屬性星岗。
作用域提供了監(jiān)視數(shù)據(jù)模型變化的能力填大。它允許開發(fā)者使用其中的apply
機(jī)制,將數(shù)據(jù)模型的變化在整個(gè)應(yīng)用范圍內(nèi)進(jìn)行通知俏橘。我們在作用域的上下文中定義和執(zhí)行表達(dá)式允华,同時(shí)它也是將事件通知給另一個(gè)控制器和應(yīng)用其他部分的中介。
視圖和$scope
AngularJS啟動(dòng)并生成視圖時(shí)寥掐,會將根ng-app
元素同$rootScope
進(jìn)行綁定靴寂。$rootScope
是所有$scope
對象的最上層。
$rootScope
是AngularJS中最接近全局作用域的對象曹仗。在$rootScope
上附加太多業(yè)務(wù)邏并不是好主意榨汤,這與污染JS的全局作用域是一樣的。
$scope
對象就是一個(gè)普通的JS對象怎茫,我們可以在其上隨意修改或添加屬性收壕。
$scope
對象充當(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
對象断国,把它設(shè)置到這個(gè)子對象上嗤锉。使用ng-controller
指令可以將一個(gè)控制器對象附加到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
對象香缺,并將它嵌套在$rootScope
中手销。
$scope的生命周期
當(dāng)AngularJS關(guān)心的事件發(fā)生在瀏覽器中時(shí),比如用戶在通過ng-model
屬性監(jiān)控的輸入字段中輸入图张,或者帶有ng-click
屬性的按鈕被點(diǎn)擊時(shí)原献,AngularJS的事件循環(huán)都會啟動(dòng)馏慨。這個(gè)事件將在AngularJS執(zhí)行上下文中處理。
每當(dāng)事件被處理時(shí)姑隅,$scope
就會對定義的表達(dá)式求值。此時(shí)事件循環(huán)會啟動(dòng)倔撞,并且AngularJS應(yīng)用會監(jiān)控應(yīng)用程序內(nèi)的所有對象讲仰,臟值檢測循環(huán)也會運(yùn)行。
$scope
對象的生命周期處理有四個(gè)不同階段痪蝇。
- 創(chuàng)建
在創(chuàng)建控制器或指令時(shí)鄙陡,AngularJS會用$injector
創(chuàng)建一個(gè)新的作用域,并在這個(gè)新建的控制器或指令運(yùn)行時(shí)將作用域傳遞進(jìn)去躏啰。 - 鏈接
當(dāng)AngularJS開始運(yùn)行時(shí)趁矾,所有的$scope
對象都會附加或者鏈接到視圖中。所有創(chuàng)建$scope
對象的函數(shù)也會將自身附加到視圖中给僵。這些作用域?qū)援?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
對象上(被稱作$rootScope
),每個(gè)子作用域都執(zhí)行自己的臟值檢測蹲诀。每個(gè)監(jiān)控函數(shù)都會檢查變化斑粱。如果檢測到任意變化,$scope
對象就會觸發(fā)指定的回調(diào)函數(shù)脯爪。 - 銷毀
當(dāng)一個(gè)$scope
在視圖中不再需要時(shí)则北,這個(gè)作用域?qū)謇砗弯N毀自己。
盡管永遠(yuǎn)不會需要清理作用域(因?yàn)锳ngularJS會為你處理)痕慢,但是知道是誰創(chuàng)建了這個(gè)作用域還是有用的尚揣,因?yàn)槟憧梢允褂眠@個(gè)$scope
上叫做$destory()
的方法來清理這個(gè)作用域。
指令和作用域
指令通常不會創(chuàng)建自己的$scope
守屉,但也有例外惑艇。比如ng-controller
和ng-repeat
指令會創(chuàng)建自己的子作用域并將它們附加到DOM元素上。
控制器
控制器的作用是增強(qiáng)視圖拇泛。在AngularJS中的控制器是一個(gè)函數(shù)滨巴,用來向視圖的作用域中添加額外的功能。我們用它來給作用域?qū)ο笤O(shè)置初始狀態(tài)俺叭,并添加自定義行為恭取。
當(dāng)我們在頁面上創(chuàng)建一個(gè)新的控制器時(shí),AngularJS會生成并傳遞一個(gè)新$scope
給這個(gè)控制器熄守◎诳澹可以在這個(gè)控制器里初始化$scope
耗跛。由于AngularJS會負(fù)責(zé)處理控制器的實(shí)例化過程,我們只需編寫構(gòu)造函數(shù)即可攒发。
function FirstController($scope) {
$scope.message = "hello";
}
我們是在全局作用域中創(chuàng)建的這個(gè)函數(shù)调塌。這樣做并不合適,因?yàn)闀廴救置臻g惠猿。更合理的方式是創(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都會調(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
的作用域中润讥,或其父級的$scope
中。
控制器可以將與一個(gè)獨(dú)立視圖相關(guān)的業(yè)務(wù)邏輯封裝在一個(gè)獨(dú)立的容器中盘寡。
控制器并不適合用來執(zhí)行DOM操作楚殿、格式化或數(shù)據(jù)操作,以及除存儲數(shù)據(jù)模型之外的狀態(tài)維護(hù)操作竿痰。它只是視圖和$scope
之間的橋梁脆粥。
AngularJS允許在$scope
上設(shè)置包括對象在內(nèi)的任何類型的數(shù)據(jù),并且在視圖中還可以展示對象的屬性影涉。
app.controller('MyController', function($scope) {
$scope.person = {
name: 'Ari Lerner'
};
});
在擁有ng-controller='MyController'
這個(gè)屬性的元素內(nèi)部的任何子元素中变隔,都可以訪問person
對象,因?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
對象用來從數(shù)據(jù)模型向視圖傳遞信息。同時(shí)鲜棠,它也可以用來設(shè)置事件監(jiān)聽器肌厨,同應(yīng)用的其他部分進(jìn)行交互,以及創(chuàng)建與應(yīng)用相關(guān)的特定業(yè)務(wù)邏輯豁陆。
控制器嵌套(作用域包含作用域)
AngularJS應(yīng)用的任何一個(gè)部分柑爸,無論它渲染在哪個(gè)上下文中,都有父級作用域存在盒音。對于ng-app
所處的層級來講表鳍,它的父級作用域就是$rootScope
馅而。有一個(gè)例外:在指令內(nèi)部創(chuàng)建的作用域被稱作孤立作用域。除了孤立作用域外譬圣,所有的作用域都通過原型繼承而來瓮恭,也就是說它們都可以訪問父級作用域。
默認(rèn)情況下胁镐,AngularJS在當(dāng)前作用域中無法找到某個(gè)屬性時(shí)偎血,便會在父級作用域中進(jìn)行查找。如果AngularJS找不到對應(yīng)的屬性盯漂,會順著父級作用域一直向上尋找,直到抵達(dá)$rootScope
為止笨农。如果在$rootScope
中也找不到就缆,程序會繼續(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
對象的父級作用域就是ParentController
的$scope
對象。根據(jù)原型繼承的機(jī)制份招,我們可以在子作用域中訪問ParentController
的$scope
對象切揭。
<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)用會將復(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á)式
用{{ }}
符號將一個(gè)變量綁定到$scope
上的寫法本質(zhì)上就是一個(gè)表達(dá)式:{{expression}}
孕豹。當(dāng)用$watch
進(jìn)行監(jiān)聽時(shí),AngularJS會對表達(dá)式或函數(shù)進(jìn)行運(yùn)算十气。
表達(dá)式和eval(js)
非常相似励背,但是由于表達(dá)式由AngularJS來處理,它們有以下顯著不同的特性:
- 所有的表達(dá)式都在其所屬的作用域內(nèi)部執(zhí)行砸西,并有訪問本地
$scope
的權(quán)限 - 如果表達(dá)式發(fā)生了
TypeError
和ReferenceError
并不會拋出異常 - 不允許使用任何流程控制功能(例如
if/else
) - 可以接受過濾器和過濾器鏈
對表達(dá)式進(jìn)行的任何操作叶眉,都會在其所屬的作用域內(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會在運(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è)過程允許我們訪問定義在$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í)更新文本字符串彼念。要在字符串模板中做插值操作,需要在對象中注入$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í)會返回null
。 - trustedContext(字符串):AngularJS會對已經(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ù)會監(jiān)視$scope
上的某個(gè)屬性江醇。只要屬性發(fā)生變化就會調(diào)用對應(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è)變量來使用裆站,并對文本的變化進(jìn)行實(shí)時(shí)更新条辟。如果需要在文本中使用不同于{{ }}
的符號來標(biāo)識表達(dá)式的開始和結(jié)束,可以在$inter polateProvider
中配置宏胯。
用startSymbol()
方法可以修改標(biāo)識開始的符號羽嫡。這個(gè)方法接受一個(gè)參數(shù)。
- value(字符型):開始符號的值肩袍。
用endSymbol()
方法可以修改標(biāo)識結(jié)束的符號杭棵。這個(gè)方法也接受一個(gè)參數(shù)。
- value(字符型): 結(jié)束符號的值。
如果要修改這兩個(gè)符號的設(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é)束的符號都設(shè)置成了__
,因此需要將HTML修改成用這個(gè)符號取代{{ }}
的版本撩笆。
完整代碼:
<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>