在AngularJS中,我們的確有手動運行模板編譯的能力。例如,插值允許基於作用域上的某個條件實時更新文本字符串。
要在字符串模板中做插值操作,需要在你的對象中注入$interpolate服務。在下面的例子中,我們將會將它注入到一個控制器中:
angular.module('myApp',[])
.controller('myController',function($scope,$interpolate){
//我們同時擁有訪問$scope、$interpolate服務的權限
}) ;
$interpolate服務是一個可以接受三個參數的函數,其中第一個參數是必需的。
- text(字符串):一個包含字符插值標記的字符串。
- mustHaveExpression(布爾型):如果將這個參數設爲true,當傳入的字符串中不含有表達式時返回null,而不是我們期望的interpolation function。
- trustedContext(字符串):AngularJS會對已經進行過字符串插值操作的字符串通過$sec.getTrusted()方法進行嚴格的上下文轉義。
$interpolate服務返回一個函數,用來在特定的上下文中運算表達式。
設置好這些參數後,就可以在控制器中進行字符串插值的操作了。例如,假設我們希望可以在電子郵件的正文中進行實時編輯,當文本發生變化時進行字符插值操作並將結果展示出來。
<div ng-controller="myController">
<input ng-model="to" type="email" placeholder="Recipient">
<textarea ng-model="emailBody"></textarea>
<pre>{{previewText}}</pre>
</div>
由於控制器內部設置了一個需要每次變化都重新進行字符插值的自定義輸入字段,因此需要設置一個$watch來監聽數據的變化。爲了保證示例的完整性,在這裏我們爲$watch引入完整的代碼。
- 簡而言之, $watch函數會監視$scope上的某個屬性。只要屬性發生變化就會調用對應的函數。可以使用$watch函數在$scope上某個屬性發生變化時直接運行一個自定義函數。
在控制器中,我們設置了$watch來監視郵件正文的變化,並將emailBody屬性的值進行字符插值後的結果賦值給previewText屬性。
angular.module('myApp',[])
.controller('myController',function($scope,$interpolate){
$scope.$watch('emailBody',function(body){
var template = $interpolate(body) ;
$scope.previewText = template({to : $scope.to}) ;
})
}) ;
現在,在{{ previewText }}內部的文本中可以將{{ to }}當做一個變量來使用,並對文本的變化進行實時更新。
- 如果需要在文本中使用不同於{{ }}的符號來標識表達式的開始和結束,可以在$inter polateProvider中配置。
用startSymbol()方法可以修改標識開始的符號。這個方法接受一個參數。
- value(字符型) :開始符號的值。
用endSymbol()方法可以修改標識結束的符號。這個方法也接受一個參數。
- value(字符型) : 結束符號的值。
如果要修改這兩個符號的設置,需要在創建新模塊時將$interpolateProvider注入進去。下面我們來創建一個服務:
angular.module('emailParser',[]).config(['$interpolateProvider',function($interpolateProvider){
$interpolateProvider.startSymbol('__') ;
$interpolateProvider.endSymbol('__') ;
}]).factory('EmailParser',['$interpolate',function($interpolate){
//處理解析的服務
return {
parse : function(text,context){
var template = $interpolate(text) ;
return template(context) ;
}
}
}]) ;
現在,我們已經創建了一個模塊,可以將它注入到應用中,並在郵件正文的文本中運行這個郵件解析器:angular.module('myApp', ['emailParser'])
.controller('MyController', ['$scope', 'EmailParser',function($scope, EmailParser) {
// 設置監聽
$scope.$watch('emailBody', function(body) {
if (body) {
$scope.previewText = EmailParser.parse(body, {
to: $scope.to
});
}
});
}]);
現在用自定義的 __ 符號取代默認語法中的 {{ }} 符號來請求插值文本。由於我們將表達式開始和結束的符號都設置成了__,因此需要將HTML修改成用這個符號取代{{ }}的版本,效果如圖所示。
<div id="emailEditor">
<input ng-model="to" type="email" placeholder="Recipient" />
<textarea ng-model="emailBody"></textarea>
</div>
<div id="emailPreview">
<pre>__ previewText __</pre>
</div>