zoukankan      html  css  js  c++  java
  • 理解$watch、$apply与$digest

    Angular环境

    浏览器里面有一个事件队列(event queue),用户触发啥事儿,或者网络请求,延时操作(例如定时器之类),都是一个event,浏览器会轮询这些事件,然后调用这些回调(这里的回调简单来说可以理解为触发一个函数),然后就进入JavaScript的环境中执行(JavaScript context),在这里面可以改变数据,操作DOM(也就是html结构),然后再退出JavaScript环境,又进入浏览器环境,然后浏览器根据之前的改动重新绘制界面,这就是个一个流程。

    Angular在javascript context内定义了一个称为angular context(Angular环境)的执行环境,非angular环境的那部分环境称为经典环境(classic context)

    $watch队列

    angular环境中也有一个队列,叫$watch队列,列表里装着被监视的变量,每当你绑定了一些东西到你的UI上,就会往$watch队列中插入一个$watch

    eg1:

    <input type="text" ng-model= "a"/>
    <input type="text" ng-model= "b"/>

    这就添加了两个$watch

    eg2:

    <input type="text" ng-model= "a"/>

    $scope.a= "11"; $scope.b= "22";

    添加了一个$watch,因为虽然有两个变量,但绑定到UI上的只有a

    eg3:

    <ul>
      <li ng-repeat="person in people">
        {{person.name}} - {{person.age}}
      </li>
    </ul>

    $scope.people= [...] //长度为3

    绑定了3*2+ 1= 7个$watch,其中1为people

    另外:当我们使用$watch函数时,也是基于这种原理,往$watch队列中添加变量

    eg:

    $scope.$watch('a', function(newValue, oldValue){

    })

    这就往$watch队列中添加了a

    $digest循环

    当事件进入angular context时,$digest将被触发,而它将遍历$watch队列

    例如:

    访问a

    a的值未发生改变

    访问b

    b改变了,那么这次检查发现了"脏值",有DOM需要更新

    继续访问

    。。。

    理想状态下只循环一次,但只要发现脏值,循环就得继续,直到所有的$watch不发生变化,再更新DOM

    但如果循环超过10次,将抛出异常,以防止无限循环

    但其实$digest不会只执行一次!

    让我们做一个假设:

    当一个$digest循环运行时,watchers会被执行来检查scope中的models是否发生了变化。如果发生了变化,那么相应的listener函数就会被执行。

    这涉及到一个重要的问题。如果listener函数本身会修改一个scope model呢?AngularJS会怎么处理这种情况?

    答案是$digest循环不会只运行一次。在当前的一次循环结束后,它会再执行一次循环用来检查是否有models发生了变化!这就是脏检查(Dirty Checking)

    它用来处理在listener函数被执行时可能引起的model变化。因此,$digest循环会持续运行直到model不再发生变化,或者$digest循环的次数达到了10次。因此,尽可能地不要在listener函数中修改model

    值得注意的是:

    每一个进入angular context的时间都会执行一次$digest循环,而每次循环都会检查整个页面的所有$watch

    $apply

    那么由什么决定事件是否进入angular context?这就得靠$apply了

    当有事件触发时,会调用$apply,而当你触发ng-click的事件时,或者更改变量的值时,事件会被装到一个$apply中调用,也就是说,默认调用了$apply!

    这就是为什么的jQuery不会更新绑定的数据,他不会调用$apply,因此需要我们手动调用

  • 相关阅读:
    数值的扩展
    字符串的扩展
    变量的解构赋值整理
    let和const命令整理
    解析vue2.0中render:h=>h(App)的具体意思
    菜单栏的显示与隐藏
    vue的事件绑定
    CSS3实现3D地球自转行星公转
    MongoDB命令的简单操作(一)
    canvas扇形进度圈动态加载
  • 原文地址:https://www.cnblogs.com/yanze/p/6384680.html
Copyright © 2011-2022 走看看