我知道,無論Watchers
和Observers
就將計算的東西在AngularJS $scope
變化。但不明白這兩者之間究竟有什麼區別。
我最初的理解是,Observers
計算爲角表達式這些都對其中作爲執行Watchers
當執行$scope.$watch()
功能的HTML側條件。我在想什麼?
我知道,無論Watchers
和Observers
就將計算的東西在AngularJS $scope
變化。但不明白這兩者之間究竟有什麼區別。
我最初的理解是,Observers
計算爲角表達式這些都對其中作爲執行Watchers
當執行$scope.$watch()
功能的HTML側條件。我在想什麼?
$observe()是Attributes對象的方法,因此,它只能用於觀察/觀察DOM屬性的值更改。它只用於/叫做內部指令。當您需要觀察/觀看包含插值的DOM屬性(即{{}})時,請使用$ observe。
例如,attr1="Name: {{name}}"
,然後在指令中:attrs.$observe('attr1', ...)
。
(如果您嘗試使用scope.$watch(attrs.attr1, ...)
,則{{}}將不起作用 - 您將獲得undefined
。)使用$ watch查看其他所有內容。
$watch()比較複雜。它可以觀察/觀察「表達式」,其中表達式可以是函數或字符串。如果該表達式是一個字符串,則它是$parse'd(即,被評估爲Angular expression)到一個函數中。 (這個函數被稱爲每個摘要循環。)字符串表達式不能包含{{}}。 $表是Scope對象上的方法,所以它可以用於/被叫無論你可以使用一個範圍對象,因此,在
因爲字符串作爲角表達式求值,當你想觀察$腕錶經常使用/觀看模型/範圍屬性。例如,attr1="myModel.some_prop"
,然後在控制器或鏈接功能中:scope.$watch('myModel.some_prop', ...)
或scope.$watch(attrs.attr1, ...)
(或scope.$watch(attrs['attr1'], ...)
)。
(如果你嘗試attrs.$observe('attr1')
,你會得到字符串myModel.some_prop
,這可能不是你想要的。)
正如對@PrimosK的回答評論所述,所有$觀察和$手錶都檢查每digest cycle。
隔離範圍的指令更復雜。如果使用'@'語法,您可以$觀察或$ watch一個包含插值(即{{}})的DOM屬性。 (它與$ watch一起工作的原因是因爲'@'語法對我們來說是interpolation,因此$ watch會看到一個沒有{{}}的字符串。)爲了讓它更容易記住在什麼時候使用,我建議使用$也觀察這種情況。
爲了幫助測試所有這些,我寫了一個Plunker,它定義了兩個指令。其中一個(d1
)不創建新範圍,另一個(d2
)創建隔離範圍。每個指令具有相同的六個屬性。每個屬性都是$ observe'd和$ watch'ed。
<div d1 attr1="{{prop1}}-test" attr2="prop2" attr3="33" attr4="'a_string'"
attr5="a_string" attr6="{{1+aNumber}}"></div>
查看控制檯日誌,查看鏈接函數中$ observe和$ watch之間的差異。然後點擊鏈接,看看哪些$ observes和$ watch是由點擊處理程序所做的屬性更改觸發的。
請注意,當鏈接函數運行時,任何包含{{}}的屬性都不會被評估(因此如果您嘗試檢查屬性,則會得到undefined
)。查看插值的唯一方法是使用$ observe(或者如果使用'@'隔離範圍,則使用$ watch)。因此,獲取這些屬性的值是異步操作。 (這就是爲什麼我們需要$觀察和$手錶的功能。)
有時你不需要$ observe或$ watch。例如,如果你的屬性包含一個數字或一個布爾值(不是字符串),只需評估一次:attr1="22"
,然後在你的鏈接函數中:var count = scope.$eval(attrs.attr1)
。如果它只是一個常量字符串– attr1="my string"
–那麼只需在您的指令中使用attrs.attr1
(不需要$ eval())。
另請參閱Vojta's google group post約$ watch表達式。
如果我理解你的問題,你問的是什麼是如果你註冊聽衆回撥$watch
或如果你這樣做$observe
。
當執行$digest
時,會觸發註冊爲$watch
的回調。請參閱docs瞭解更多信息。
當包含插值的屬性的值更改(例如attr="{{notJetInterpolated}}"
)時,將調用註冊爲$observe
的回調。
內部指令,你可以使用這兩者非常相似的方式:
attrs.$observe('attrYouWatch', function() {
// body
});
或
scope.$watch(attrs['attrYouWatch'], function() {
// body
});
其實,因爲每一個變化都會反映在'$ digest'階段,所以'$ digest'回調將被安全地假定'$ digest'中被調用。 '$ digest'中也會調用'$ watch'回調函數,但每當值被更改時。我認爲他們完成同樣的工作:「觀察表達式,調用回調值改變」。關鍵字差異可能只是語法糖,不會讓開發人員感到困惑。 – 2013-02-14 16:34:33
@fastreload,我完全同意你的評論..寫得很好! – PrimosK 2013-02-14 20:22:14
@fastreload ...感謝您的精彩解釋。如果我理解正確,觀察者是爲了角度表達。我對嗎? – Abilash 2013-02-15 03:17:52
我覺得這是很明顯的:
記住:兩個函數有兩個參數,
$observe/$watch(value : string, callback : function);
function (oldValue, newValue)
我做了一個plunker,所以你可以實際掌握它們的使用情況。我已經使用變色龍比喻來更容易拍照。
你的編輯沒有幫助,有點拮抗。請體諒其他人來這裏尋求實際幫助。 – smalone 2016-08-17 02:01:36
@smalone改變了。感謝和抱歉! – Abilash 2016-08-22 08:13:27
不用擔心。感謝您的修復。 – smalone 2016-09-15 18:21:30