>

银河娱乐在线:更新承诺发布新旗舰以及更多内

- 编辑:银河娱乐平台 -

银河娱乐在线:更新承诺发布新旗舰以及更多内

银河娱乐在线 1

AngularJs 的要素与模型双向绑定正视于循环检查测量检验它们之间的值,这种做法叫做脏检测,方今研商了须臾间其源码,将 Angular 的得以完成分享一下。

不行流行的MMO网络电子游艺《星球大战前夜》迎来了118.6更新,更新将要星期五三月22日发布,更新承诺发布一款崭新旗舰,该战舰就要新伊甸的战场中巡查。巨蛇海盗强势归来,并带给三支全新战船,首先只可以出今后玩乐事件中,前边能够在小卖部买到。可惜的是末端具体怎么时候不明了。

首先拜访哪些将 Model 的转移更新到 UI

那不是两全更变内容。游戏画面也将收获更新,那款游戏已经有13年时间了,别的还是能够获取Scope Network,能够让您看见全新挑战和职务,那几个都在6周末子的事件中生出。每便你做到贰个挑衅,都会在你的Scope Network上列出。这个战利品箱包蕴奖赏。

Angular 的 Model 是一个 Scope 的种类,各样 Scope 都归于于三个 Directive 对象,举个例子 $rootScope 就归于于 ng-app。

从 ng-app 往下,各类 Directive 创制的 Scope 都会一层一层链接下去,产生四个以 $rootScope 为根的链表,注意 Scope 还应该有同级的概念,形容更适用小编以为应该是一棵树。

我们大致看一下 Scope 都有如何成员:

  function Scope() {       this.$id = nextUid();       // 依次为: 阶段、父 Scope、Watch 函数集、下一个同级 Scope、上一个同级 Scope、首个子级 Scope、最后一个子级 Scope       this.$$phase = this.$parent = this.$$watchers =                      this.$$nextSibling = this.$$prevSibling =                      this.$$childHead = this.$$childTail = null;           // 重写 this 属性以便支持原型链       this['this'] = this.$root =  this;       this.$$destroyed = false;       // 以当前 Scope 为上下文的异步求值队列,也就是一堆 Angular 表达式       this.$$asyncQueue = [];       this.$$postDigestQueue = [];       this.$$listeners = {};       this.$$listenerCount = {};       this.$$isolateBindings = {}; }

银河娱乐在线:更新承诺发布新旗舰以及更多内容,双向绑定机制解析。Scope.$digest,那是 Angular 提供的从 Model 更新到 UI 的接口,你从哪些 Scope 调用,那它就能够从那么些 Scope 初步遍历,通知模型修正给各样 watch 函数,
来看看 $digest 的源码:

$digest: function() {     var watch, value, last,         watchers,         asyncQueue = this.$$asyncQueue,         postDigestQueue = this.$$postDigestQueue,         length,         dirty, ttl = TTL,         next, current, target = this,         watchLog = [],         logIdx, logMsg, asyncTask;      // 标识阶段,防止多次进入     beginPhase('$digest');      // 最后一个检测到脏值的 watch 函数     lastDirtyWatch = null;      // 开始脏检测,只要还有脏值或异步队列不为空就会一直循环     do {       dirty = false;       // 当前遍历到的 Scope       current = target;        // 处理异步队列中所有任务, 这个队列由 scope.$evalAsync 方法输入       while(asyncQueue.length) {         try {           asyncTask = asyncQueue.shift();           asyncTask.scope.$eval(asyncTask.expression);         } catch (e) {           clearPhase();           $exceptionHandler(e);         }         lastDirtyWatch = null;       }        traverseScopesLoop:       do {         // 取出当前 Scope 的所有 watch 函数         if ((watchers = current.$$watchers)) {           length = watchers.length;           while (length--) {             try {               watch = watchers[length];                if (watch) {                 // 1.取 watch 函数的运算新值,直接与 watch 函数最后一次值比较                 // 2.如果比较失败则尝试调用 watch 函数的 equal 函数,如果没有 equal 函数则直接比较新旧值是否都是 number 而且都是 NaN                 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 函数的变更通知函数, 也就是说各个 directive 从这里更新 UI                   watch.fn(value, ((last === initWatchVal) ? value : last), current);                    // 当 digest 调用次数大于 5 的时候(默认10),记录下来以便开发人员分析。                   if (ttl < 5) {                     logIdx = 4 - ttl;                     if (!watchLog[logIdx]) watchLog[logIdx] = [];                     logMsg = (isFunction(watch.exp))                         ? 'fn: '   (watch.exp.name || watch.exp.toString())                         : watch.exp;                     logMsg  = '; newVal: '   toJson(value)   '; oldVal: '   toJson(last);                     watchLog[logIdx].push(logMsg);                   }                 } else if (watch === lastDirtyWatch) {                   // If the most recently dirty watcher is now clean, short circuit since the remaining watchers                   // have already been tested.                   dirty = false;                   break traverseScopesLoop;                 }               }             } catch (e) {               clearPhase();               $exceptionHandler(e);             }           }         }          // 恕我理解不能,下边这三句是卖萌吗         // Insanity Warning: scope depth-first traversal         // yes, this code is a bit crazy, but it works and we have tests to prove it!         // this piece should be kept in sync with the traversal in $broadcast          // 没有子级 Scope,也没有同级 Scope         if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {           // 又判断一遍不知道为什么,不过这个时候 next === undefined 了,也就退出当前 Scope 的 watch 遍历了           while(current !== target && !(next = current.$$nextSibling)) {             current = current.$parent;           }         }       } while ((current = next));         // 当 TTL 用完,依旧有未处理的脏值和异步队列则抛出异常       if((dirty || asyncQueue.length) && !(ttl--)) {         clearPhase();         throw $rootScopeMinErr('infdig',             '{0} $digest() iterations reached. Aborting!n'               'Watchers fired in the last 5 iterations: {1}',             TTL, toJson(watchLog));       }      } while (dirty || asyncQueue.length);      // 退出 digest 阶段,允许其他人调用     clearPhase();      while(postDigestQueue.length) {       try {         postDigestQueue.shift()();       } catch (e) {         $exceptionHandler(e);       }     }   }

虽说看起来十分长,不过超轻易掌握,默许从 $rootScope 初步遍历,对各样 watch 函数求值比较,现身新值则调用通告函数,由通告函数更新 UI,大家来会见ng-model 是怎么注册布告函数的:

本文由银河会员注册发布,转载请注明来源:银河娱乐在线:更新承诺发布新旗舰以及更多内