AngularJs $parse、$eval和$observe、$watch詳解
$parse和$eval
$parse和$eval這兩個函數(shù)都可以解析表達式的值.
它們的區(qū)別在于$parse是一個服務(wù), 可以注入使用. $eval是scope對象上的一個方法, 我們只能在能訪問scope的場景下使用它.
var getter = $parse('user.name'); var setter = getter.assign; var context = {user: {name: 'John Doe'}; var locals = {user: {name: 'Doe John'}; getter(context); //John Doe setter(context, 'new name'); getter(context); //new name getter(context, locals); //Doe John
$parse服務(wù)接收一個表達式作為參數(shù)并返回一個函數(shù). 這個函數(shù)可以被調(diào)用, 其中的參數(shù)是一個context對象, 通常來說是作用域.
另外, 這個函數(shù)有一個assign屬性. 它也是一個函數(shù), 可以用來在給定的上下文中改變這個表達式的值. 最后一行代碼演示了如何使用locals來覆蓋context對象.
$eval用起來要簡單很多, 因為它的上下文已經(jīng)被指定為scope對象.
var scope = $rootscope.$new(true); scope.a = 1; scope.b = 2; scope.$eval('a + b')//3 scope.$eval(function(scope){ return scope.a + scope.b; });//3
關(guān)于$parse和$eval之間的關(guān)系, 我們能從Angular源碼中看出來, 可以說$eval是為了讓$parse在scope中使用更方便的語法糖.
$eval: function(expr, locals){ return $parse(expr)(this, locals); }
$eval還有個同胞兄弟, $evalAsync, 它并不會立刻計算表達式的值, 而是將表達式緩存起來, 等到下一次$digest ( 臟檢查 ) 的時候執(zhí)行. 以獲取更好的性能.
$observe和$watch
$observe和$watch都可以監(jiān)聽表達式值的變化. 但有顯著的不同.
$observe是angular指令中l(wèi)ink函數(shù)第三個參數(shù) ( attrs ) 的一個方法. 只能在指令的link函數(shù)中使用它. 它是通過$evalAsync函數(shù)實現(xiàn)監(jiān)控的.
$watch是scope對象上的一個方法, watch表達式很靈活, 可以是一個函數(shù), 可以是scope上的屬性, 也可以是一個字符串形式的表達式. 監(jiān)聽scope上的屬性名或表達式的時候, 會利用$parse服務(wù)將表達式轉(zhuǎn)換成一個函數(shù), 這個函數(shù)會在$digest中被調(diào)用. $watch的第三個參數(shù)"objectEquality", 指定比較對象的方式, 如果為true,則用angular.equals, 否則直接比較引用. 默認為false.
//html <div book="{{book.name}}"></div> //js attrs.$observe('book', function(newValue){ //just have one parameter, can't get old value }); scope.$watch(attrs.book, function(newValue, oldValue){ //get undefined });
當你需要監(jiān)聽一個包含"{{}}"的DOM屬性時, 使用$observe, 如果用$watch, 只能得到undefined. 反之, 就用$watch. 如果用$observe, 只能得到一個固定的字符串.
//html <div book="book.name"></div> //js attrs.$observe('book', function(newValue){ //always get 'book.name' }); scope.$watch(attrs.book, function(newValue, oldValue){ });
有一個特殊的情況, 當你的指令使用了獨立的作用域 ( scope:{} ) , 那些應(yīng)用了"@"語法的DOM屬性, 即使包含"{{ }}", 也可以被$watch.
因為@前綴標識符, 它的實現(xiàn)是通過$observe去監(jiān)聽DOM屬性的變化, 這就是為什么@attr的值只能是字符串或是"{{}}", 而不能是scope上的屬性, 所以最終$watch看到的表達式是沒有"{{ }}"的. 而"="和"&"則是基于$watch實現(xiàn). 所以=attr, &attr的值不能包含"{{ }}", 但可以直接使用scope上的屬性.
$watchGroup和$watchCollection
$watchGroup是用來監(jiān)聽一組表達式. 數(shù)組中任意表達式的變化都會觸發(fā)監(jiān)聽函數(shù).
$scope.teamScore = 0; $scope.time = 0; $scope.$watchGroup(['teamScore', 'time'], function(newVal, oldVal) { //newVal and oldVal are both array });
$watchCollection用來監(jiān)聽一個對象(包括數(shù)組), 當這個對象的任意屬性發(fā)生變化時, 觸發(fā)監(jiān)聽函數(shù). 和$watch一樣,第一次參數(shù)可以是一個返回一個對象的函數(shù).
$scope.names = ['igor', 'matias', 'misko', 'james']; $scope.dataCount = 4; $scope.$watchCollection('names', function (newVal, oldVal) { $scope.dataCount = newVal.length; }); $timeout(function(){ $scope.names.pop(); },2000);
$observe, $watch, $watchGroup, $watchCollection都返回一個移除監(jiān)聽的函數(shù). 當需要取消監(jiān)聽的時候, 直接調(diào)用.
var off = scope.$watch('name', function(newValue, oldValue){ }); off();
以上就是對AngularJs $parse、$eval和$observe、$watch的知識詳解,謝謝大家對本站的支持!
相關(guān)文章
AngularJS實現(xiàn)根據(jù)變量改變動態(tài)加載模板的方法
這篇文章主要介紹了AngularJS實現(xiàn)根據(jù)變量改變動態(tài)加載模板的方法,結(jié)合實例形式簡單分析了AngularJS動態(tài)加載模板的主要操作技巧與模板實現(xiàn)代碼,需要的朋友可以參考下2016-11-11angular6.0開發(fā)教程之如何安裝angular6.0框架
這篇文章主要介紹了angular6.0開發(fā)教程之如何安裝angular6.0框架,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06angularjs的單選框+ng-repeat的實現(xiàn)方法
今天小編就為大家分享一篇angularjs的單選框+ng-repeat的實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09詳解基于Bootstrap+angular的一個豆瓣電影app
本篇文章主要介紹了基于Bootstrap+angular的一個豆瓣電影app ,非常具有實用價值,需要的朋友可以參考下2017-06-06在Angular中使用NgTemplateOutlet創(chuàng)建可重用組件的流程步驟
在 Angular 中,使用 NgTemplateOutlet 而不是創(chuàng)建特定組件,可以使組件在不修改組件本身的情況下輕松修改為各種用例,在本文中,您將接受一個現(xiàn)有組件并重寫它以使用 NgTemplateOutlet,需要的朋友可以參考下2024-03-03AngularJS基礎(chǔ) ng-paste 指令簡單示例
本文主要介紹AngularJS ng-paste 指令,這里對ng-paste 指令的基礎(chǔ)資料做了整理,并附有代碼示例,有需要的朋友可以參考下2016-08-08詳解在AngularJS的controller外部直接獲取$scope
本篇文章主要介紹了詳解在AngularJS的controller外部直接獲取$scope ,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06