JavaScript 事件管理
在设计JavaScript xxsdk的时候考虑到能让调用者参与到工作流程中来,开始用了回调函数。如下:
this.foo = function(args,callbackFn) {
//do something
//then if callbackFn is a function
callbackFn();
};
或者在初始化的传入config。
function SDK(config) {
var configs = {
onInit: function() {
},
onFoo: function () {
},
// on....
};
//合并参数
configs = $.extend(configs, config);
this.foo = function (args) {
//do something
configs.onFoo();
};
}
但问题来了,随着函数越多,第一种方式就显得很烦,每个方法的参数后面要跟一个或者多个回调函数,代码显得不干净,而且只有用户调用的时候才会执行回调,对于没有暴露给用户的方法就用不上。第二种方式,函数越多,config就越长,构造代码显得难看,另一方面就是一个方法只会触发一个回调。最后使用了下面的方式
事件管理
先定义一个事件管理器,主要思路是让每一个事件类型对应一个回调列表,这样可以让外部对同一个事件关联多次。取消某个关联就是在该事件类型的函数列表中移除某个回调函数。触发就是把列表中函数全部执行一遍。当然还带上了参数。
var eventManger = {
handlers: {},
//类型,绑定事件
addHandler:function(type,handler) {
if (typeof this.handlers[type] == "undefined") {
this.handlers[type] = [];//每个事件都可以绑定多次
}
this.handlers[type].push(handler);
},
removeHandler:function(type, handler) {
var events = this.handlers[type];
for (var i = 0, len = events.length; i < len; i++) {
if (events[i] == handler) {
events.splice(i, 1);
break;
}
}
},
trigger: function (type) {
if (this.handlers[type] instanceof Array) {
var handlers = this.handlers[type];
var args = Array.prototype.slice.call(arguments, 1);
for (var i = 0, len = handlers.length; i < len; i++) {
handlers[i].apply(null, args);
}
}
}
};
然后在sdk中公布关联和移除的方法:
//给外部绑定事件
this.on = function(type, event) {
eventManger.addHandler(type,event);
};
//移除事件
this.off = function(type, event) {
eventManger.removeHandler(type, event);
};
在执行的过程中分别触发事件:
this.init = function() {
//do init
eventManger.trigger('init');
};
this.start = function() {
//do start
eventManger.trigger('start');
};
this.connect = function() {
eventManger.trigger('connect');
};
this.messages = function() {
var msgs = [];
msgs.push("你好吗");
msgs.push("我很好");
eventManger.trigger('messages',msgs);
};
this.disconnect = function() {
eventManger.trigger('disconnect');
};
那用户在使用的时候就比较方便了。
//绑定connect
sdk.on('connect', function () {
console.log('connect');
});
//绑定messages
sdk.on('messages', function (data) {
if (!data) return; if (data instanceof Array) {
for (var i = 0; i < data.length; i++) {
console.log(data[i]);
}
} else {
console.log(data);
}
});
还可以先绑定,移除再绑定。
var oninit = function() {
console.log('init...');
};
sdk.on('init', oninit);
sdk.on('init', function () {
console.log('other init');
});
sdk.off('init', oninit);
sdk.init();
全部代码:
function SDK() { var eventManger = {
handlers: {},
//类型,绑定事件
addHandler:function(type,handler) {
if (typeof this.handlers[type] == "undefined") {
this.handlers[type] = [];//每个事件都可以绑定多次
}
this.handlers[type].push(handler);
},
removeHandler:function(type, handler) {
var events = this.handlers[type];
for (var i = 0, len = events.length; i < len; i++) {
if (events[i] == handler) {
events.splice(i, 1);
break;
}
}
},
trigger: function (type) {
if (this.handlers[type] instanceof Array) {
var handlers = this.handlers[type];
var args = Array.prototype.slice.call(arguments, 1);
for (var i = 0, len = handlers.length; i < len; i++) {
handlers[i].apply(null, args);
}
}
}
};
//给外部绑定事件
this.on = function(type, event) {
eventManger.addHandler(type,event);
};
//移除事件
this.off = function(type, event) {
eventManger.removeHandler(type, event);
}; this.init = function() {
//do init
eventManger.trigger('init');
};
this.start = function() {
//do start
eventManger.trigger('start');
};
this.connect = function() {
eventManger.trigger('connect');
};
this.messages = function() {
var msgs = [];
msgs.push("你好吗");
msgs.push("我很好");
eventManger.trigger('messages',msgs);
};
this.disconnect = function() {
eventManger.trigger('disconnect');
}; this.autoRun = function() {
this.init();
this.start();
this.connect();
this.messages();
this.disconnect();
}; } var sdk = new SDK();
var oninit = function() {
console.log('init...');
};
sdk.on('init', oninit);
sdk.on('start', function () {
console.log('start');
});
sdk.on('connect', function () {
console.log('connect');
});
sdk.on('messages', function (data) {
if (!data) return; if (data instanceof Array) {
for (var i = 0; i < data.length; i++) {
console.log(data[i]);
}
} else {
console.log(data);
}
});
sdk.on('disconnect', function () {
console.log('disconnect');
}); sdk.autoRun();
sdk.on('init', function () {
console.log('other init');
});
sdk.off('init', oninit);
sdk.init();
执行结果:
还可以扩展一些方法once() 、removeListener() 、removeAllListeners()֖等
小结:事件的处理方式更加简洁且更有扩展性。jquery的事件机制没有将事件监听函数绑定到DOM元素上,而是基于数据缓存模块来管理的。这里借鉴了下,对同一事件类型type的所有监听对象handleObj构成监听对象数组handles。因为没有涉及到dom操作,所以相对也简单些。
JavaScript 事件管理的更多相关文章
- JavaScript事件详解-Zepto的事件实现(二)【新增fastclick阅读笔记】
正文 作者打字速度实在不咋地,源码部分就用图片代替了,都是截图,本文讲解的Zepto版本是1.2.0,在该版本中的event模块与1.1.6基本一致.此文的fastclick理解上在看过博客园各个大神 ...
- jquery技巧之让任何组件都支持类似DOM的事件管理
本文介绍一个jquery的小技巧,能让任意组件对象都能支持类似DOM的事件管理,也就是说除了派发事件,添加或删除事件监听器,还能支持事件冒泡,阻止事件默认行为等等.在jquery的帮助下,使用这个方法 ...
- JavaScript事件详解-zepto的事件实现
zepto的event 可以结合上一篇JavaScript事件详解-原生事件基础(一)综合考虑源码暂且不表,github里还有中文网站都能下到最新版的zepto.整个event模块不长,274行,我们 ...
- vuejs单一事件管理组件间的通信
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Javascript事件模型(一):DOM0事件和DOM2事件
javascript事件模型,本文主要有以下内容: DOM0事件模型 DOM2事件模型 一.DOM0事件模型 早期的事件模型称为DOM0级别. DOM0的事件具有极好的跨浏览器优势, 会以最快的速度 ...
- JavaScript事件代理和委托
在javasript中,代理.委托经常出现. 那么它究竟在什么样的情况下使用?它的原理又是什么? 这里介绍一下javascript delegate的用法和原理,以及Dojo,jQuery等框架中de ...
- MUI事件管理
模块:事件管理 http://dev.dcloud.net.cn/mui/event/ 事件绑定: 除了可以使用addEventListener()方法监听某个特定元素上的事件外, 也可以使用.on( ...
- 系统事件管理(Events) ---- HTML5+
模块:events Events模块管理客户端事件,包括系统事件,如扩展API加载完毕.程序前后台切换等. 比如说:网络的链接的和断开这种事件,系统从前台走到后台这种事件: 不包括:点击和滑动页面事件 ...
- JavaScript 事件委托
JavaScript事件委托,或者叫事件代理,是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件. 借花献佛的例子(取快递): 有三个同事预计会在周一收到快递.为签收快递,有两种办法 ...
随机推荐
- 手机端页面rem自适应脚本
什么是rem 参照 web app变革之rem 在我看来,rem就是1rem单位就等于html节点fontsize的像素值.所以改变html节点的fontsize是最为关键的一步.根据手机宽度改变相对 ...
- 基于Codeigniter框架实现的APNS批量推送—叮咚,查水表
最近兼职公司已经众筹成功的无线门铃的消息推送出现了问题,导致有些用户接收不到推送的消息,真是吓死宝宝了,毕竟自己一手包办的后台服务,影响公司信誉是多么的尴尬,容我简单介绍一下我们的需求:公司开发的是一 ...
- Java集合框架练习-计算表达式的值
最近在看<算法>这本书,正好看到一个计算表达式的问题,于是就打算写一下,也正好熟悉一下Java集合框架的使用,大致测试了一下,没啥问题. import java.util.*; /* * ...
- (转) JAVA中如何设置图片(图标)自适应Jlable等组件的大小
一.问题: 一个程序,组件上设置某个图片作为图标,因为的label(应该说是组件)已经设定了固定大小, 所以再打开一些大图片时,超过组件大小的部分没显示出来,而小图片又没填充完整个组件 二.解决这个问 ...
- 公共资源情报(OSINT)工具Automater
公共资源情报(OSINT)工具Automater 公共资源情报(OSINT)就是从公共信息中提取有用情报.它是美国中央情报局(CIA)的一种情报搜集手段,各国都在广泛利用这种方式.Kali Lin ...
- php 二位数组按某个键值排序
$arr=[ array( 'name'=>'小坏龙', 'age'=>28 ), array( 'name'=>'小坏龙2', 'age'=>14 ), array( 'na ...
- C++-Qt【2】-实现一个简单的记事本
用Qt实现一个简单的记事本: #include "helloqt.h" #include <qfiledialog.h> #include <qfile.h> ...
- hdu3549还是网络流
最后一次训练模板(比较熟练了) 接下来训练网络流的建图 #include <cstdio> #define INF 2147483647 int n,m,ans,x,y,z,M,h,t,T ...
- centos中docker mongodb 配置
安装docker,对于Centos7,如下: $ sudo yum update$ sudo yum -y install docker$ sudo systemctl start docker 首先 ...
- host Object和native Object的区别
Native Object: JavaScript语言提供的不依赖于执行宿主的对象,其中一些是内建对象,如:Global.Math:一些是在脚本运行环境中创建来使用的,如:Array.Boolean. ...