我知道,当$scope
中的某些东西在AngularJS中发生变化时,Watchers
和Observers
都会被计算出来.但我不明白这两者到底有什么区别.
我最初的理解是,Observers
是为Angular 表达式计算的,这是HTML端的条件,当执行$scope.$watch()
函数时执行as Watchers
.我想得对吗?
我知道,当$scope
中的某些东西在AngularJS中发生变化时,Watchers
和Observers
都会被计算出来.但我不明白这两者到底有什么区别.
我最初的理解是,Observers
是为Angular 表达式计算的,这是HTML端的条件,当执行$scope.$watch()
函数时执行as Watchers
.我想得对吗?
$observe() is a method on the Attributes object, and as such, it can only be used to observe/watch the value change of a DOM attribute. It is only used/called inside directives. Use $observe when you need to observe/watch a DOM attribute that contains interpolation (i.e., {{}}'s).
E.g., attr1="Name: {{name}}"
, then in a directive: attrs.$observe('attr1', ...)
.
(If you try scope.$watch(attrs.attr1, ...)
it won't work because of the {{}}s -- you'll get undefined
.) Use $watch for everything else.
$watch() is more complicated. It can observe/watch an "expression", where the expression can be either a function or a string. If the expression is a string, it is $parse'd (i.e., evaluated as an Angular expression) into a function. (It is this function that is called every digest cycle.) The string expression can not contain {{}}'s. $watch is a method on the Scope object, so it can be used/called wherever you have access to a scope object, hence in
因为字符串是作为Angular 表达式计算的,所以当您想要观察/观察模型/范围属性时,通常使用$watch.例如,attr1="myModel.some_prop"
,然后在控制器或链路功能中:scope.$watch('myModel.some_prop', ...)
或scope.$watch(attrs.attr1, ...)
(或scope.$watch(attrs['attr1'], ...)
).
正如@PrimosK的答案 comments 中所讨论的,所有$observes和$watches每digest cycle次判断一次.
Directives with isolate scopes are more complicated. If the '@' syntax is used, you can $observe or $watch a DOM attribute that contains interpolation (i.e., {{}}'s). (The reason it works with $watch is because the '@' syntax does the interpolation for us, hence $watch sees a string without {{}}'s.) To make it easier to remember which to use when, I suggest using $observe for this case also.
为了帮助测试所有这些,我编写了一个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>
查看控制台日志(log),查看链接功能中$observe和$watch之间的差异.然后单击链接,查看单击处理程序所做的属性更改触发了哪些$observes和$watches.
请注意,当link函数运行时,包含{{}的所有属性都尚未计算(因此,如果您try 判断这些属性,将得到undefined
).查看插值的唯一方法是使用$observe(如果使用带"@"的隔离作用域,则使用$watch).因此,获取这些属性的值是一个简单的操作.(这就是为什么我们需要$observe和$watch功能.)
Sometimes you don't need $observe or $watch. E.g., if your attribute contains a number or a boolean (not a string), just evaluate it once: attr1="22"
, then in, say, your linking function: var count = scope.$eval(attrs.attr1)
. If it is just a constant string – attr1="my string"
– then just use attrs.attr1
in your directive (no need for $eval()).
另见Vojta's google group post美元左右的手表表情.