angularjs $evalAsync()实现原理

来源:互联网 发布:直播源码下载 编辑:程序博客网 时间:2024/05/21 19:31

《angularjs权威教程》是怎么说的

  • angular扩展了 addEventListener的流程
  • angular事件循环通常称为$digest循环
  • $digest循环分两步:$watch列表,$evalAsync列表

    • 一个用作ui的$scope属性,向$watch列表增加一个函数
    • $watch列表会在$digest循环中被“脏值检查”解析
    • 脏值检查维护一个旧值一个新值一个isDirty就好
    • $scope.$watch( expression , callback )用于给$digest循环手动装配一个脏值检测,如果expression的值检测到变化,则多$digest循环一次
    • $scope.$watch()的返回是它本身的注销函数
    • ng-click后,会绑定onclick时间,调用$scope.$apply(),从而再次进入$digest循环


    • $digest循环运行的第二个操作是执行$$asyncQueue。可以使用$evalAsync()方法访问这个工作队列??这什么意思??

    • 脏值检查完毕后,asyncQueue队列是空的,所以我们在脏值检测阶段通过$evalAsync()把函数加到队列里,然后执行异步列表,然后再来一轮$digest循环
  • $apply()让你从angular框架外部搞一个函数到angular上下文里面去执行,$apply随后还会调用$digest循环。所有ng-[event]指令都会调用$apply()!!!

源代码是怎么写的

看源码痛苦了好几天,找不到切入口。经人建议,从$scope.$apply看起。

$apply()

Scope.prototype = {    $apply: function(expr){        try {            beginPhase('$apply');            return this.$eval(expr);        } finally {            clearPhase();            try {                $rootScope.$digest();            }        }           }}function beginPhase(phase) {    $scope.$$phase = phase;}   

可以看出,$apply()基本上除了调用$digest()啥都没做

/********* $digest() line 15039 *******/do {    dirty = false;    current = target;       //     while(asyncQueue.length) {        try {            asyncTask = asyncQueue.shift();            asyncTask.scope.$eval(asyncTask.expression, asyncTask.locals); //如何用$evalAsync()访问这个队列?        }        do {            if((watchers = current.$$watchers)) {                length = watchers.length;                while( length-- ) {                    watch = watchers[length];                    if(watch) {                        if((value=watch.get(current)) !== (last=watch.last) && !(watch.eq ?                             equals(value,last):                            (typeof value==='number' && typeof last==='number' && isNaN(value) && isNaN(last) ))) {                            dirty = true;                            lastDirtyWatch = watch;                            watch.last = watch.eq?copy(value,null) : value;                            watch.fn(value,((last===initWatchVal))                    }                 }            }        } while ((current=next))    }   }

compile

/*--------- line 6098 ---------*/
0 0
原创粉丝点击