事件分布的
作用 当我们为页面添加各种交互
函数时,我们知道的最简单的
方法是绑定页面元素的事件,然后在事件
处理函数中
执行我们想要做的
操作:
element.onclick =函数(事件){
做任何事情。
};
如果我们要做的动作并不复杂,那么这里的实际逻辑函数代码就可以了。如果将来需要
修改它,那么将它
转换为事件处理函数的
位置。
此外,为了进行适当的代码重用,我们可以将部分逻辑函数拆分为函数:
element.onclick =函数(事件){
这里的代码。 /其他
DoSomethingElse();
};
该函数的
功能dosomethingelse这里可以用在其他地方,所以它会裂开。另外,可能有功能,如
设置坐标。假设的函数名的位置,我们需要使用的
浏览器事件对象的事件提供的信息,如指针位置。
element.onclick =函数(事件){
这里的代码。 /其他
DoSomethingElse();
位置(event.clientx,事件。clienty);
};
一个不
推荐这里的东西是通过事件对象直接设定的位置上。这是因为它是区分逻辑函数与事件之间听两种责任的良好实践。只有事件处理函数本身是与浏览器事件对象事件的联系,这有助于降低代码的耦合促进
独立的测试和
维护。
那么,越来越多的功能,越来越复杂,会是什么呢如果你按照以前的做法,它可能是这样的:
element.onclick =函数(事件){
domission1();
domission2(event.clientx,事件。clienty);
domission3();
…
DoMissionXX();
};
虽然这不是问题,但这一次可以考虑更优雅的写作风格:
element.onclick =函数(事件){
Amplify.publish(绫:点击
X:event.clientx,
Y:event.clienty
});
};
此表单为事件分发。请注意,这里的事件不涉及浏览器
本地事件(事件对象),但逻辑级自定义事件,绫:点击以上是真正的自定义事件的名称。
很明显,这还没有结束,为了完成我们以前所拥有的复杂功能,我们还需要将定制事件与我们想做的事情联系起来。
amplify.subscribe(绫:点击
…
amplify.subscribe(绫:点击
…
看起来又回来了是的,但它很有用。一方面,浏览器本地事件侦听被分离和固化。在改变逻辑函数,如减少几个函数后,只需要
删除自定义事件的相关代码部分,而不必关心本地事件,另一方面,逻辑功能的
调整变得更加灵活。它可以在任何代码位置添加订阅功能,并且可以自己进行
分类管理。
简单地说,事件分发可以增加定制事件的冗余度(当它只是一个简单的逻辑函数时,您会认为它是多余的),减少代码模块之间的耦合,使逻辑功能更加清晰和有序,便于后续维护。
等等,前面几次出站的放大镜是多少
很好,是时候
介绍一下了。
amplifyjs
事件分发需要某种方式来实现它。实现事件分发的设计
模式之一是发布/订阅(发布/订阅)。
amplifyjs是一个简单的Javascript库,它主要提供三种功能,Ajax请求,数据存储、发布/订阅(每个可以独立使用)。其中,发布/订阅为
核心功能,以及相应的
名字是amplify.core。
amplify.core是简洁、明确的实施发布/订阅设计模式,共有超过100行的注释。在阅读源代码的放大,你可以得到一个更好地了解如何实现发布/订阅设计模式。
代码全景
对amplify.core源代码的整体结构如下:
函数(全局的,未定义的){
var切片,
订阅= {;
放大global.amplify = { { var =
发布:函数(主题){
…
},
订阅:函数(主题,上下文,回调,优先级){
…
},
取消订阅:函数(主题,上下文,回调){
…
}
};
}(这个);
如您所见,放大定义了一个全局变量,称为放大(作为全局的
属性),它有3种方法:发布、订阅和取消订阅。此外,订阅作为本地变量,将
保存在发布/订阅模式中涉及的所有自定义事件名和相关函数。
发布
发布已发布,它需要指定一个主题,即自定义事件名(或主题)。调用后,将依次调用与主题相
关联的所有函数。
发布:函数(主题){
{ { 1 }
如果(typeof的话题!=字符串){
抛出新
错误(您必须提供一个有效的发布主题。);
}
{ { 2 }
var args = slice.call(
参数1),
topicsubscriptions,
订阅,
长度,
我= 0,
RET;
如果(!订阅{主题}){
返回true;
}
{ { 3 }
topicsubscriptions =订阅{主题}片();
为(长度= topicsubscriptions.length;i <长度;i++){
订阅= topicsubscriptions {我};
ret = subscription.callback.apply(subscription.context,args);
如果(false = false){
打破;
}
}
返回= false = false;
},
{ 1 },参数主题必须是字符串,否则会引发错误。
{ 2 },将所有参数传递到发布功能除了话题并保存在数组形式的其他参数。如果对应的主题不在订阅,它直接返回。
{ 3 },topicsubscriptions,作为一个数组,获取相关的所有元素在一个主题,其中包括两部分,回调和
背景。然后,遍历元素,每个元素的回调被调用,而元素的上下文带来的元件和附加参数args前进。如果任何相关元素的回调函数返回FALSE,然后停止
运行并返回false。
订阅
订阅,如单词的含义(如杂志中的某些内容),是建立主题与回调之间关联的
步骤。优先级越小,优先级越高,
默认值为10。事实上,一个话题的所有相关元素
都是根据优先级从高到低预先排列的。
订阅:函数(主题,上下文,回调,优先级){
如果(typeof的话题!=字符串){
抛出新错误(您必须提供一个有效的主题来
创建一个));
}
{ { 1 }
如果(arguments.length = 3种回调=数){
优先级=回调;
回调=上下文;
上下文= null;
}
如果(arguments.length = 2){
回调=上下文;
上下文= null;
}
优先级=优先| | 10;
{ { 2 }
无功topicindex = 0,
主题= topic.split( / /),
topiclength = topics.length,
补充;
为(;;topicindex < topiclength;topicindex ++){
主题=主题topicindex } {;
添加= false;
如果(!订阅{主题}){
订阅{主题} { };
}
{ { 3 }
var =订阅=主题.长度- 1,
subscriptioninfo = { {
回调:回调,
上下文:上下文,
优先级:优先级
};
{ { 4 }
为((= = 0;i)){
如果(订阅{主题,我优先} =优先级){
订阅{主题}。剪接(i + 1, 0,subscriptioninfo);
添加=真;
打破;
}
}
{ { 5 }
如果(!添加){
订阅主题} { Unshift(subscriptioninfo);
}
}
返回回调;
},
{ 1 },为了理解这一部分,请参见放大所提供的api示意图:
amplify.subscribe(字符串的题目,函数调用)
amplify.subscribe(字符串的主题,对象,函数调用)
Amplify.subscribe (string topic, function callback, number priority)
Amplify.subscribe(
字符串主题,对象上下文,函数回调,数字优先级)
可以看出,放大允许多个参数的形式,但在数量和
类型的参数是不同的,在一个特定的位置的参数可以被视为不同的内容。这也是许多其他Javascript库看到。这样,多参数的形式可以由数量的判断和参数式设计。
{ 2 },当您订阅时,主题被允许为空格。空白字符将用作分隔符。它被认为是将回调关联到多个主题,因此将使用一个循环。添加作为标识符来指示新添加的元素是否已添加到数组中,最初是错误的。
{ 3 },每个回调函数的保存实际上是一个对象,除了回调和上下文(缺省为null)和优先级。
{ 4 },环路是基于优先级的值来找到相关的元素的位置。任何相关元素的主题是从无到有、从小到大按照优先级的值设置(
命令)。因此,相比较而言,假设是新添加的元素的优先级(低优先级),数值比较大的数组,只要相关元素的优先级数值比小原数组的新的元素,这个周期可以被打断,可以添加到新添加的元素在拼接阵列的方法。如果循环运行直到完成,这是可以确定,新添加的元素的优先级值是最小的,并说将保持不初始值为假。
{ { 5 },如果未将元素添加到该位置,则添加和剪切可以确保元素位于数组的前面(或第一个元素)。
退订
虽然出版和订阅是最重要的,但会有退款的时间(杂志不想看到决定性的撤退!)所以,你需要退订。
取消订阅:函数(主题,上下文,回调){
如果(typeof的话题!=字符串){
抛出新错误(您必须提供一个有效的主题删除a));
}
如果(arguments.length = 2){
回调=上下文;
上下文= null;
}
如果(!订阅{主题}){
返回;
}
变量长度=订阅,
我= 0;
为(;;i;<长度;i + +){
如果(订阅,{,主题,我=回调=回调){
如果(上下文订阅{话题我| |!{上下文=上下文){
订阅{主题剪接(i,1);
调整计数器和长度,以便删除 /项
我--;
长度-;
}
}
}
}
在阅读了以前的源代码后,这一部分似乎很容易理解。遍历指定元素的关联元素,找到一致的回调函数,并删除它。由于使用了拼接方法,原始数组将被直接修改,因此有必要手动调整i和长度。
放大使用的例子
官方使用的例子之一是:
amplify.subscribe(dataexample
警报(数据);
});
…
Amplify.publish(dataexample
与先前的源代码部分相结合,对发布/订阅的设计模式有更清楚的理解吗
补充说明
您可能还注意到,典型的发布/订阅amplifyjs
同步(同步)。也就是说,当运行amplify.publish(主题),会有一个主题的所有运行在回调没有延迟。
后记
酒吧/子是一个相对容易理解的设计模式,但它是应付大型
应用程序的复杂的逻辑非常有用。本文的amplifyjs简要分析我写的更简洁和相关规则(单功能)的Javascript库,所以在这里和大家
分享。