AngularJS:$ observe和$ watch方法之间的区别
我知道,只要AngularJS中$scope
某些内容发生变化, Watchers
和Observers
被计算出来。 但不明白这两者之间究竟有什么区别。
我最初的理解是Observers
计算角度表达式,这是HTML端的条件,当$scope.$watch()
函数执行时, Watchers
执行这些条件。 我在想什么?
$ observe()是Attributes对象上的一个方法,因此它只能用于观察/观察DOM属性的值更改。 它只用于/叫做内部指令。 当您需要观察/观看包含插值的DOM属性(即{{}})时,请使用$ observe。
例如, attr1="Name: {{name}}"
,然后在一个指令中: attrs.$observe('attr1', ...)
。
(如果你尝试使用scope.$watch(attrs.attr1, ...)
,它将不会工作,因为{{}} - 你会得到undefined
。)使用$ watch scope.$watch(attrs.attr1, ...)
其他事情。
$ watch()更复杂。 它可以观察/观察“表达式”,其中表达式可以是函数或字符串。 如果表达式是一个字符串,则它是$ parse'd(即,作为一个Angular表达式求值)到一个函数中。 (这个函数被称为每个摘要循环。)字符串表达式不能包含{{}}。 $ watch是Scope对象上的一个方法,所以只要你有权访问范围对象,就可以使用/调用它
因为字符串被评估为Angular表达式,所以当你想观察/观察一个模型/范围属性时,经常使用$ watch。 例如, attr1="myModel.some_prop"
,然后在控制器或链接函数中: scope.$watch('myModel.some_prop', ...)
或scope.$watch(attrs.attr1, ...)
(或scope.$watch(attrs['attr1'], ...)
)。
(如果你尝试attrs.$observe('attr1')
你会得到字符串myModel.some_prop
,这可能不是你想要的。)
正如@ PrimosK的回答中所讨论的那样,所有$ observes和$ watch都会在每个摘要周期中进行检查。
隔离范围的指令更复杂。 如果使用'@'语法,您可以$ observe或$观察包含插值的DOM属性(即{{}})。 (与$ watch一起工作的原因是因为'@'语法为我们插值,因此$ 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关于$ watch表达式的谷歌群组文章。
如果我理解你的问题,你会问如果你使用$watch
注册监听器回调或者使用$observe
注册,那么你会发现什么是不同的。
使用$watch
$digest
注册的回调会在执行$digest
时触发。
当包含插值的属性的值更改(例如attr="{{notJetInterpolated}}"
)时,将调用注册到$observe
回调。
在内部指令中,你可以以非常相似的方式使用它们两个:
attrs.$observe('attrYouWatch', function() {
// body
});
要么
scope.$watch(attrs['attrYouWatch'], function() {
// body
});
我认为这很明显:
请记住:这个函数有两个参数,
$observe/$watch(value : string, callback : function);
function (oldValue, newValue)
我已经做了一个笨蛋,所以你可以实际掌握它们的使用情况。 我已经使用变色龙比喻来更容易拍照。
链接地址: http://www.djcxy.com/p/13643.html上一篇: AngularJS : Difference between the $observe and $watch methods