AngularJS:$ observe和$ watch方法之间的区别

我知道,只要AngularJS中$scope某些内容发生变化, WatchersObservers被计算出来。 但不明白这两者之间究竟有什么区别。

我最初的理解是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对象上的一个方法,所以只要你有权访问范围对象,就可以使用/调用它

  • 一个控制器 - 任何控制器 - 一个通过ng-view,ng-controller或者一个指令控制器创建的控制器
  • 一个指令中的链接函数,因为它也可以访问范围
  • 因为字符串被评估为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用于范围内观察其值的任何变化。
  • 请记住:这个函数有两个参数,

    $observe/$watch(value : string, callback : function);
    
  • value :始终是对watched元素的字符串引用(作用域变量的名称或要监视的指令属性的名称)
  • 回调函数:要执行的function (oldValue, newValue)
  • 我已经做了一个笨蛋,所以你可以实际掌握它们的使用情况。 我已经使用变色龙比喻来更容易拍照。

    链接地址: http://www.djcxy.com/p/13643.html

    上一篇: AngularJS : Difference between the $observe and $watch methods

    下一篇: AngularJS $http and $resource