深入理解AngularJs-scope的脏检查(一)

  

进入正文前的说明:本文中的示例代码并非AngularJs源码,而是来自书籍& lt; & lt;构建自己的AngularJs>在这本书的作者仅依赖jquery和lodash一步一步构建出AngularJs的各核心模块,对全面理解AngularJs有非常巨大的帮助。若有正在使用AngulaJs攻城拔寨并且希望完全掌握手中武器的小伙伴,相信能对你理解AngularJs带来莫大帮助,感谢作者。

  

在这篇文章中,希望能让您理清楚以下几项与范围相关的功能:
  

  

1.脏检查(脏检测)核心机制,主要包括:手表和消化美元;
  

  

2。几种不同的触发美元消化循环的方式:eval美元,用美元,evalAsync美元,美元applyAsync;
  

  

3。范围的继承机制以及范围隔离;
  

  

4。依赖于范围的事件循环:美元,广播,释放美元。

  

<强>现在开始我们的第一部分:范围和脏检查

  

脏检查(脏检测)原理简述:范围通过看美元方法向。$ $观察家数组中添加观察家对象(包含watchFn, listenerFn, valueEq,最后四个属性)。每美元当消化循环被触发时,它会遍历$ $观察家数组,执行观察者中的watchFn,获取当前范围上某属性的值(一个观察者对应范围上一个被监听属性),然后去同观察者中最后的(上一次的值)做比较,若两值不相等,就执行listenerFn。
  

        函数作用域(){   这一点。$ $观察家=[];//监听器数组   这一点。$ $ lastDirtyWatch=零;//每次消化循环的最后一个脏的观察家,用于优化消化循环   这一点。$ $ asyncQueue=[];//范围上的异步队列   这一点。$ $ applyAsyncQueue=[];//范围上的异步队申请列   这一点。$ $ applyAsyncId=零;//异步申请信息   这一点。$ $ postDigestQueue=[];//postDigest执行队列   这一点。$ $阶段=零;//储存范围上正在做什么,值有:消化/应用/空   这一点。$ root=;//rootScope      这一点。$ $听众={};//存储包含自定义事件键值对的对象      这一点。儿童$ $=[];//存储当前范围的儿子范围,以美元便消化循环递归   }      之前      

实际上就范围是一个普通的javascript对象,一个类构造函数,可以通过新的进行实例化。根据脏检测的原理,接下来,我们一起看看的范围看美元方法的实现。
  

     /*美元看方法:向观察者数组中添加观察家对象,以便对应调用*/Scope.prototype。看美元=函数(watchFn、listenerFn valueEq) {   var自我=;      watchFn=$解析(watchFn);//watchDelegate:针对表表达式是常量和>   Scope.prototype。$ $ digestOnce=function () {   var脏;   var continueLoop=true;   var自我=;      这个。$ $ everyScope(函数(范围){   var newValue oldValue;      _.forEachRight(范围。$ $观察家,函数(观察者){   尝试{   如果(观察者){   newValue=https://www.yisu.com/zixun/watcher.watchFn(范围);   oldValue=watcher.last;      如果(!范围。$ $ areEqual (newValue oldValue watcher.valueEq)) {   美元范围。根。$ $ lastDirtyWatch=观察者;      观察者。去年=(观察者。valueEq吗?_.cloneDeep (newValue): newValue);      watcher.listenerFn (newValue   (oldValue===initWatchVal ?newValue: oldValue)、范围);   脏=true;   }else if(范围。根。$ $ lastDirtyWatch===观察家){   continueLoop=false;   返回错误;   }   }   }捕捉(e) {   console.error (e);   }   });   返回continueLoop;   });      返回脏;   };      之前      

代码中,$ $ everyScope是递归childScope执行回调函数的工具方法,后面会贴出。

  

digestOnce美元的核心逻辑就在$ $ everyScope方法的循环体内,即遍历范围。$ $观察家,比对新旧值,根据比对结果确定是否执行listenerFn,并向listenerFn中传入newValue, oldValue、范围供开发者获取。

  

示例代码第18行,watcher.last的赋值证实了上文提到美元的手表的第三个参数valueEq的作用。

  

示例代码第23行,由于美元消化循环会一直运行直到没有肮脏的观察者时,故单次美元消化循环通过缓存最后一个肮脏的观察者,在下一次消化美元循环时如果遇到$ $ lastDirtyWatcher就停止当前循环。这样做减少了遍历观察者的数量,优化了性能。

  

<>强,外层循环

  

在我们的示例中,外层循环即由美元消化来控制。美元消化函数主要由在循环体内调用美元digestOnce进行脏检测以及对其他一些异步操作的处理组成。代码如下:

深入理解AngularJs-scope的脏检查(一)