Angular學(xué)習(xí)筆記(1)—初識(shí)AngularJS

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-controllerng-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ā)生了TypeErrorReferenceError并不會(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>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容