[AngularJS面面观] 11. scope事件机制 - 事件系统在Angular框架
此篇文章是angular事件机制相关的最后一篇文章。 移除scope后的广播有过定义指令(directive)经验的同学们应该知道,很多指令都会拥有自己的scope,无论是隔离scope也好,还是原型继承的scope也好。这些指令在浏览器中也是通过对应模板(template)所表示的DOM元素来刷存在感的。而显然,伴随业务逻辑的执行,一些指令对应的DOM元素会被创建,使用和销毁。 DOM的创建就意味着资源的分配,比如DOM元素的样式修饰,事件的绑定等等。而这些资源并不是无限的,因此当该DOM被销毁的时候,就需要有办法能够回收这些资源。典型的比如jQuery中的 具体而言,是如何做到呢? 首先,在创建scope的时候,就会监听一个名为 $new: function(isolate,parent) {
// 构建新的scope,定义为child
// ......
// 为什么只有隔离scope和parent被显示指定的情况下才需要注册$destroy的回调?
// 因为回调函数destroyChildScope中的唯一操作就是将当前scope上的$$destroyed属性置为true
// 而这个$$destroyed属性在其它情况下都会通过原型继承机制共享给当前scope的所有孩子
if (isolate || parent != this) child.$on('$destroy',destroyChildScope);
return child;
}
function destroyChildScope($event) {
$event.currentScope.$$destroyed = true;
}
除了在创建scope时就未雨绸缪考虑到了将来删除这个scope时需要调用的回调函数外,在应用程序代码的任何地方也能够根据需要为某个scope创建一个删除事件( 这只是事件系统的一环,一个巴掌拍不响,注册了用于监听的回调函数。还需要有个地方触发。对于scope的删除事件,触发它的任务就自然而然落在了 $destroy: function() {
// 避免重复删除scope
if (this.$$destroyed) return;
var parent = this.$parent;
// 广播$destroy事件后将标志位$$destroyed置为true
this.$broadcast('$destroy');
this.$$destroyed = true;
if (this === $rootScope) {
// 应用程序终止的清理工作
$browser.$$applicationDestroyed();
}
// 更新各种事件的回调函数数量
incrementWatchersCount(this,-this.$$watchersCount);
for (var eventName in this.$$listenerCount) {
decrementListenerCount(this,this.$$listenerCount[eventName],eventName);
}
// 调整scope树结构,剥离当前被删除scope的存在感 --- 一些指针操作
if (parent && parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
if (parent && parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;
// 将各种方法无效化,防止错误调用。清除回调函数字典对象
this.$destroy = this.$digest = this.$apply = this.$evalAsync = this.$applyAsync = noop;
this.$on = this.$watch = this.$watchGroup = function() { return noop; };
this.$$listeners = {};
// 继续调整scope树结构,cleanUpScope针对IE9作了一些特殊处理,具体请参考相关代码
this.$$nextSibling = null;
cleanUpScope(this);
}
代码中的注释简单解释了一下对应部分代码起到的作用。具体的清理过程就不继续深究了,感兴趣的同学可以仔细阅读一下相关源代码。 下面我们看看在什么地方会调用这个定义在scope对象上的 if (value) {
// 当ng-if后表达式解析为true时执行的代码
} else {
// 当ng-if后表达式解析为false时执行的代码
// ......
if (childScope) {
childScope.$destroy();
childScope = null;
}
// ......
}
那么当ng-if后表达式解析为false时,就会删除它对应的scope。所以这也意味着如果ng-if表达式的值变化的比较频繁,那么scope的创建和销毁也会比较频繁。如果在你的应用代码中使用了非常多的ng-if而发现应用有时卡顿比较明显的话,不妨考虑一下使用ng-show这一指令,它并不会导致频繁的scope创建和销毁。 ———————————–未完待续—————————————— 随着这一系列文章的更新,我们也会了解越来越多angular内部的实现原理。如果其中用到了事件机制,在这篇文章中也会继续更新。 敬请期待。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |