[AngularJS面面观] 9. scope事件机制 - 基本概念以及生命周期
在前面的8篇文章中,已经介绍了scope的几个方面,比如digest循环,继承机制等。 主要分为以下6个方面进行讨论: 本文首先讨论1-2。下一篇文章中讨论3-5。最后一篇文章讨论6。 发布-订阅模式(Publish-Subscribe Pattern)这个模式算是设计模式中经典中的经典了。是消息中间件必然要实现的模式之一,也被众多框架以及API所支持。该模式在大规模分布式系统中是不可或缺的,它将系统中的消息产生者和消息消费者解耦开来,提高了系统的可扩展性。关于这个模式的概念和定义,这里就不再赘述了。对这个概念还不熟悉的同学们可以移步这里学习一下:英文Wiki。想看具体代码的同学网上搜索一下相关资料非常多。 那么当上下文变成了angular,发布订阅模式又是如何被实现和应用的呢? 那么问题来了,事件机制怎么和scope继承树融为一体的呢?嗯,不要心急,待我一一道来。 事件的生命周期-注册实现其实不复杂,直接贴上代码一起分析一下: $on: function(name,listener) {
// listeners字典对象的初始化
var namedListeners = this.$$listeners[name];
if (!namedListeners) {
this.$$listeners[name] = namedListeners = [];
}
namedListeners.push(listener);
// 更新listenerCount计数器字典对象
var current = this;
do {
if (!current.$$listenerCount[name]) {
current.$$listenerCount[name] = 0;
}
current.$$listenerCount[name]++;
} while ((current = current.$parent));
// 提供注销该listener的函数
var self = this;
return function() {
var indexOfListener = namedListeners.indexOf(listener);
if (indexOfListener !== -1) {
namedListeners[indexOfListener] = null;
decrementListenerCount(self,1,name);
}
};
}
// 内部使用的用于减少计数器的方法
function decrementListenerCount(current,count,name) {
do {
current.$$listenerCount[name] -= count;
if (current.$$listenerCount[name] === 0) {
delete current.$$listenerCount[name];
}
} while ((current = current.$parent));
}
首先我们根据文档来看看这个 /** /* @param {string} name 需要监听的事件名称。 * @param {function(event,...args)} 当事件发生时,需要执行的listener回调函数。 * @returns {function()} 返回一个用户注销事件的函数。 */
$on: function(name,listener){}
一目了然,这里在注册事件的时候就考虑到了注销,而采取的策略和在scope中定义watcher一致,都是返回一个注销函数,当需要注销此回调函数的时候调用一下即可。
至于一些细节部分,不懂的地方仔细体会一下即可。 function createChildScopeClass(parent) {
function ChildScope() {
this.$$watchers = this.$$nextSibling =
this.$$childHead = this.$$childTail = null;
this.$$listeners = {}; // 用于保存事件对应的回调函数
this.$$listenerCount = {}; // 用于保存事件对应回调函数的计数器
this.$$watchersCount = 0;
this.$id = nextUid();
this.$$ChildScope = null;
}
ChildScope.prototype = parent;
return ChildScope;
}
事件的生命周期-注销对于事件的注销,过程上和注册非常相似,只不过正好相反: return function() {
var indexOfListener = namedListeners.indexOf(listener);
if (indexOfListener !== -1) {
namedListeners[indexOfListener] = null;
decrementListenerCount(self,name);
}
};
在调用注销函数后,首先得到注册的回调函数在数组中的位置,当存在时将其置为空并更新计数器。 总结一下,目前发现的angular中事件的几个特点: angular事件和浏览器事件一些题外话。 当需要在angular中定义浏览器事件的相应方法时,通常可以使用angular.element方法。这个方法也比较智能,当它判断jQuery可用时,会使用jQuery来初始化元素。否则会使用angular中自带的jqLite进行元素的初始化。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |