我知道一旦AngularJS中$scope中的某些东西发生变化,Watchers和Observers都会被计算出来。但不明白两者到底有什么区别。
$scope
Watchers
Observers
我最初的理解是,Observers是为角表达式计算的,角表达式是HTML端上的条件,当$scope.$watch()函数执行时执行Watchers。我想得对吗?
$scope.$watch()
如果我理解你的问题正确,你问的是,如果你用$watch注册监听器回调,或者用$observe注册,有什么不同。
$watch
$observe
在执行$digest时触发与$watch注册的回调。
$digest
用$observe注册的回调函数在包含插值的属性值更改时被调用(例如attr="\{\{notJetInterpolated}}")。
attr="\{\{notJetInterpolated}}"
内部指令你可以用非常相似的方式使用它们:
attrs.$observe('attrYouWatch', function() { // body });
或
scope.$watch(attrs['attrYouWatch'], function() { // body });
attr1="Name: \{\{name}}"
attrs.$observe('attr1', ...)
scope.$watch(attrs.attr1, ...)
undefined
< a href = " http://docs.angularjs.org/api/ng。rootScope.Scope #看美元”>看美元()< / >更复杂。它可以观察/观察一个“表达式”,其中表达式可以是一个函数或字符串。如果表达式是字符串,则将其__abc1d(即计算为角表达式)转换为函数。(每个文摘周期都要调用这个函数。)字符串表达式不能包含\{\{}}。$watch是范围对象上的一个方法,因此可以在任何可以访问范围对象的地方使用/调用它,因此在
attr1="myModel.some_prop"
scope.$watch('myModel.some_prop', ...)
scope.$watch(attrs['attr1'], ...)
attrs.$observe('attr1')
myModel.some_prop
正如在@PrimosK的回答的评论中所讨论的,所有的$ observed和$watches每消化周期都会检查一次。
具有独立作用域的指令更加复杂。如果使用'@'语法,你可以$observe 或看美元一个包含插值(即\{\{}})的DOM属性。(它与$watch一起工作的原因是因为'@'语法为我们做了插值,因此$watch看到一个没有\{\{}}的字符串。)为了更容易记住何时使用哪个,我建议在这种情况下也使用$observe。
为了帮助测试所有这些,我写了一个砰砰作响,它定义了两个指令。一个(d1)不创建新的作用域,另一个(d2)创建一个隔离作用域。每个指令都有六个相同的属性。每个属性都是$ observed和$watch'ed。
d1
d2
<div d1 attr1="\{\{prop1}}-test" attr2="prop2" attr3="33" attr4="'a_string'" attr5="a_string" attr6="\{\{1+aNumber}}"></div>
查看控制台日志,查看链接函数中$observe和$watch之间的差异。然后单击链接,查看哪些$ observed和$watches是由单击处理程序所做的属性更改触发的。
请注意,当link函数运行时,任何包含\{\{}}的属性都不会计算(因此如果尝试检查属性,将得到undefined)。查看插值值的唯一方法是使用$observe(如果使用带有'@'的隔离作用域,则使用$watch)。因此,获取这些属性的值是一个异步操作。(这就是为什么我们需要$observe和$watch函数。)
有时你不需要$observe或$watch。例如,如果你的属性包含一个数字或布尔值(不是字符串),只计算它一次:attr1="22",然后在,比如说,你的链接函数:var count = scope.$eval(attrs.attr1)。如果它只是一个常量字符串–attr1="my string" mdash;然后在你的指令中使用attrs.attr1(不需要$eval())。
attr1="22"
var count = scope.$eval(attrs.attr1)
attr1="my string"
attrs.attr1
参见Vojta的谷歌群帖子中的$watch表达式。
我认为这很明显:
记住:两个函数都有两个参数,
$observe/$watch(value : string, callback : function);
function (oldValue, newValue)
我已经做了一个< kbd >恰好< / kbd >,所以你实际上可以掌握它们的使用情况。我用变色龙的比喻是为了更容易描绘。
为什么$observe和$watch不同?
在每个digest()循环中,对watchExpression进行计算并与前一个值进行比较,如果watchExpression值发生变化,则调用watch函数。
$observe专门用于观察插入的值。如果一个指令的属性值被插入,例如dir-attr="\{\{ scopeVar }}",则只有在插入的值被设置时才会调用observe函数(因此当$digest已经确定需要进行更新时)。基本上已经有了一个用于插值的观察者,而$observe函数与之相连。
dir-attr="\{\{ scopeVar }}"
参见$observe &在compile.js中设置$