• “通过事件机制,可以将类设计为独立的模块,通过事件对外通信,提高了程序的开发效率。”
  • 可以把多个关联但逻辑复杂的操作利用自定义事件的机制灵活地控制好

对象之间通过直接方法调用来交互

1)对象A直接调用对象B的某个方法,实现交互;直接方法调用本质上也是属于一种特殊的发送与接受消息,它把发送消息和接收消息合并为一个动作完成;

方法调用方和被调用方被紧密耦合在一起;因为发送消息和接收消息是在一个动作内完成,所以无法做到消息的异步发送和接收;

2)对象A生成消息->将消息通知给一个事件消息处理器(Observable)->消息处理器通过同步或异步的方式将消息传递给接收者;

这种方式是通过将消息发送和消息接收拆分为两个过程,通过一个中间者来控制消息是同步还是异步发送;

在消息通信的灵活性方面比较有优势,但是也带来了一定的复杂度。但是复杂度一般可以由框架封装,消息的发送方和接收方仍然可以做到比较简单;

总的来说就是一种松耦合的处理,2个对象之间有太多紧密的直接关联,应该要考虑通过消息通信解耦,从而提高应用程序的可维护性和重用性

在JS中,消息的通知是通过事件表达的,当代码库增长到一定的规模,就需要考虑将行为和自定义事件进行解耦。

了解自定义事件的概念

  • 类似DOM的行为:在DOM节点(包括document对象)监听并触发自定义事件。这些事件既可以冒泡,也可以被拦截。这正是Prototype、jQuery和MooTools所做的。如果事件不能扩散,就必须在触发事件的对象上进行监听。
  • 命名空间:一些框架需要你为你的事件指定命名空间,通常使用一个点号前缀来把你的事件和原生事件区分开。
  • 自定义额外数据:JavaScript框架允许你在触发自定义事件时,向事件处理器传送额外的数据。jQuery可以向事件处理器传递任意数量的额外参数。
  • 通用事件API:只用Dojo保留了操作原生DOM事件的正常API。而操作自定义事件需要特殊的发布/订阅API。这也意味着Dojo中的自定义事件不具有DOM事件的一些行为(比如冒泡)。
  • 声明:我们往往需要在预定义的事件中加入一些特殊的变化(例如,需要Alt键按下才能触发的单击事件),MooTools运行你定义此类自定义事件。此类事件需要预先声明,即便你只是声明他们的名字。任何未声明的自定义事件不会被触发。

一、jQuery自定义事件

jQuery的自定义事件是通过on和one绑定的,然后再通过trigger来触发这个事件

如有三种情况需要分别处理:

  1. 用户提交空值
  2. 用户提交的用户名不存在
  3. 用户提交的用户名存在

jQuery 提供的自定义事件可以引入语义,很好地解决问题

//1. 定义自定义事件
$('#username').on('blank.username', function() {
console.log('请不要留空');
});
$('#username').on('notExist.username', function() {
console.log('用户名不存在');
});
$('#username').on('success.username', function() {
console.log('用户名存在');
}); //2. 触发自定义事件
$('.js-submit').on('click', function() {
var username = $('#username').val();
username = $.trim(username);
if (username === '') {
$('#username').trigger('blank.username'); // 如果 username 为空值,则触发 blank.username 事件
}
$.post(url, {username: username}, function(data) {
var res = data;
if (res.retcode === -1) {
$('#username').trigger('notExist.username'); // 如果用户不存在,则触发 notExist.username 事件
} else if (res.retcode === 0) {
$('#username').trigger('success.username'); // 如果用户存在,则触发 sucess.username 事件
}
});
});

trigger需要处理的问题

1.模拟事件对象,用户模拟处理停止事件冒泡

triger()方法触发事件后,会执行浏览器默认操作。例如:

$("input").trigger("focus");

以上代码不仅会触发为input元素绑定的focus事件,也会使input元素本身得到焦点(浏览器默认操作)。

如果只想触发绑定的focus事件,而不想执行浏览器默认操作,可以使用jQuery中另一个类似的非冒泡式方法-triggerHandler()方法。

$container.one("focus",function(){
.....
});
$("input").triggerHandler("focus");

该方法会触发input元素上绑定的特定事件,同时取消浏览器对此事件的默认操作,即文本框指触发绑定的focus事件,不会得到焦点。

请注意这里使用了jQuery 的one 来代替on。这两者的区别在于,one 在触发处理器之后会自动将其删除。

2.区分事件类型,触发标准的浏览器事件 和 自定义事件名绑定的处理程序。

解决方法:事件名称+命名空间

p4.on('click.aaa.ccc',function(e,vv,c){
console.log('p4')
})
p4.trigger('click.aaa')

二、javascript的自定义事件

1. 简单的自定义事件

自定义事件到激发这个事件,需要document.createEvent(),event.initEvent(),element.dispatchEvent()这三部,分别是创建事件对象,初始化事件对象,触发事件

<div id="testBox"></div>
// 1. 创建事件
var evt = document.createEvent('HTMLEvents');
// 2. 定义事件类型,事件初始化
evt.initEvent('customEvent', true, true);
// 3. 在元素上监听事件,绑定监听
var obj = document.getElementById('testBox');
obj.addEventListener('customEvent', function(){
console.log('customEvent 事件触发了'+event.type);
}, false);
  • console 中输入 obj.dispatchEvent(evt),可以看到 console 中输出“customEvent 事件触发了”,表示自定义事件成功触发
  • 遗憾的是在 IE8 及以下版本的 IE 中并不支持document.createEvent()的方法,IE支持的 document.createEventObject()和event.fireEvent()方法,但是经过测试,fireEvent并不能用于自定义事件,传给它的参数只能是在IE已经定义了的事件,fireEvent 只支持标准事件的触发。
function foo1(){
addLog("foo1 is excute");
}
function foo2(){
addLog("the id is "+idChange.getId()+" now!");
}
if(document.createEvent){ //This is for the stand browser.
var ev=document.createEvent('HTMLEvents');
ev.initEvent('fakeEvent',false,false);
document.addEventListener("fakeEvent",foo1,false);
document.addEventListener("fakeEvent",foo2,false);
}else if(document.attachEvent){ //This is for the damn IE
document.documentElement.fakeEvents = 0; // an expando property
document.documentElement.attachEvent("onpropertychange", function(event) {
if (event.propertyName == "fakeEvents") {
foo1();
}
});
document.documentElement.attachEvent("onpropertychange",function(event){
if(event.propertyName == "fakeEvents"){
foo2();
}
});
}
function addLog(log){
var logDiv=document.getElementById('log');
var p=document.createElement("p");
p.appendChild(document.createTextNode(log));
logDiv.appendChild(p);
}
var idChange=function(){
var id=1;
return {getId:function(){return id;},
setId:function(a){
id=a;
if(document.dispatchEvent) document.dispatchEvent(ev);
else if(document.attachEvent) document.documentElement.fakeEvents++; //This for IE
}}
}();

2. 一个完整的事件机制

这个机制支持标准事件和自定义事件的监听,移除监听和模拟触发操作。需要注意的是,为了使到代码的逻辑更加清晰,这里约定自定义事件带有 'custom' 的前缀(例如:customTest,customAlert),demo

/**
* @description 包含事件监听、移除和模拟事件触发的事件机制,支持链式调用
* @author Kayo Lee(kayosite.com)
* @create 2014-07-24
*
*/ (function( window, undefined ){
var Ev = window.Ev = window.$ = function(element){
return new Ev.fn.init(element);
}; // Ev 对象构建
Ev.fn = Ev.prototype = {
init: function(element){
this.element = (element && element.nodeType == 1)? element: document;
}, /**
* 添加事件监听
*
* @param {String} type 监听的事件类型
* @param {Function} callback 回调函数
*/
add: function(type, callback){
var _that = this;
if(_that.element.addEventListener){
/**
* @supported For Modern Browers and IE9+
*/
_that.element.addEventListener(type, callback, false);
} else if(_that.element.attachEvent){
/**
* @supported For IE5+
*/
// 自定义事件处理
if( type.indexOf('custom') != -1 ){
if( isNaN( _that.element[type] ) ){
_that.element[type] = 0;
}
var fnEv = function(event){
event = event ? event : window.event
if( event.propertyName == type ){
callback.call(_that.element);
}
};
_that.element.attachEvent('onpropertychange', fnEv); // 在元素上存储绑定的 propertychange 的回调,方便移除事件绑定
if( !_that.element['callback' + callback] ){
_that.element['callback' + callback] = fnEv;
} // 标准事件处理
} else {
_that.element.attachEvent('on' + type, callback);
}
} else {
/**
* @supported For Others
*/
_that.element['on' + type] = callback;
}
return _that;
}, /**
* 移除事件监听
*
* @param {String} type 监听的事件类型
* @param {Function} callback 回调函数
*/
remove: function(type, callback){
var _that = this;
if(_that.element.removeEventListener){
/**
* @supported For Modern Browers and IE9+
*/
_that.element.removeEventListener(type, callback, false);
} else if(_that.element.detachEvent){ /**
* @supported For IE5+
*/
// 自定义事件处理
if( type.indexOf('custom') != -1 ){
// 移除对相应的自定义属性的监听
_that.element.detachEvent('onpropertychange', _that.element['callback' + callback]);
// 删除储存在 DOM 上的自定义事件的回调
_that.element['callback' + callback] = null;
// 标准事件的处理
} else {
_that.element.detachEvent('on' + type, callback);
}
} else {
/**
* @supported For Others
*/
_that.element['on' + type] = null;
}
return _that;
}, /**
* 模拟触发事件
* @param {String} type 模拟触发事件的事件类型
* @return {Object} 返回当前的 Kjs 对象
*/
trigger: function(type){
var _that = this;
try {
// 现代浏览器
if(_that.element.dispatchEvent){
// 创建事件
var evt = document.createEvent('Event');
// 定义事件的类型
evt.initEvent(type, true, true);
// 触发事件
_that.element.dispatchEvent(evt);
// IE
} else if(_that.element.fireEvent){
if( type.indexOf('custom') != -1 ){
_that.element[type]++;
} else {
_that.element.fireEvent('on' + type);
}
}
} catch(e){
};
return _that;
}
} Ev.fn.init.prototype = Ev.fn; })( window );

参考:

  • http://www.cnblogs.com/aaronjs/p/3452279.html
  • http://kayosite.com/javascript-custom-event.html
  • http://dean.edwards.name/weblog/2009/03/callbacks-vs-events/

javascript和jquey的自定义事件小结的更多相关文章

  1. javascript事件之:谈谈自定义事件(转)

    http://www.cnblogs.com/pfzeng/p/4162951.html 对于JavaScript自定义事件,印象最深刻的是用jQuery在做图片懒加载的时候.给需要懒加载的图片定义一 ...

  2. javascript事件之:谈谈自定义事件

    对于JavaScript自定义事件,印象最深刻的是用jQuery在做图片懒加载的时候.给需要懒加载的图片定义一个appear事件.当页面图片开始出现时候,触发这个自定义的appear事件(注意,这里只 ...

  3. javaScript事件机制深入学习(事件冒泡,事件捕获,事件绑定方式,移除事件方式,阻止浏览器默认行为,事件委托,模拟浏览器事件,自定义事件)

    前言 JavaScript与HTML之间的交互是通过事件实现的.事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间.可以使用侦听器(或处理程序)来预订事件,以便事件发生时执行相应的代码.这种在传统软 ...

  4. Javascript之自定义事件

    Javascript自定义事件,其本质就是观察者模式(又称订阅/发布模式),它的好处就是将绑定事件和触发事件相互隔离开,并且可以动态的添加.删除事件. 下面通过实例,一步一步构建一个具体的Javasc ...

  5. Javascript事件模型系列(四)我所理解的javascript自定义事件

    被我拖延了将近一个月的javascript事件模型系列终于迎来了第四篇,也是我计划中的最后一篇,说来太惭愧了,本来计划一到两个星期写完的,谁知中间遇到了很多事情,公司的个人的,搞的自己心烦意乱浮躁了一 ...

  6. JavaScript自定义事件

    很多DOM对象都有原生的事件支持,向div就有click.mouseover等事件,事件机制可以为类的设计带来很大的灵活性,相信.net程序员深有体会.随着web技术发展,使用JavaScript自定 ...

  7. javascript:自定义事件初探

    javascript:自定义事件初探   http://www.cnblogs.com/jeffwongishandsome/archive/2008/10/27/1317148.html

  8. Javascript 自定义事件 (custom event)

    Javascript 中经常会用到自定义事件.如何创建一个简单的自定义事件呢?在创建自定义的事件之前,我们应该考虑一下和事件有关的东西.例如 click 事件,首先我们要能注册一个click事件(在一 ...

  9. 理解的javascript自定义事件

    理解的javascript自定义事件 被我拖延了将近一个月的javascript事件模型系列终于迎来了第四篇,也是我计划中的最后一篇,说来太惭愧了,本来计划一到两个星期写完的,谁知中间遇到了很多事情, ...

随机推荐

  1. IOS UIImageView的contentMode属性

    红框表示imageView的frame,下面的图片是原图大小UIViewContentModeScaleToFill,       默认,对图片进行拉伸处理(不是按比例),是充满bouns UIVie ...

  2. easyui from 缓存问题处理

    1 这是ie低版本,缓存了easyui form load事件获取的服务器端数据,给ajax时间加上清除缓存就ok. 找到easyui 中的form load事件  添加cache:false, /* ...

  3. 一首诗,致亲爱的csdn

    来自csdn的Rachel-Zhang姐姐 还记得--致亲爱的csdn 还记得你年轻时的摸样? 简单的文字,无瑕的脸庞. 现在的你,满脸风霜. 五粮液的广告,在我的文章中久久荡漾. 还记得当初的梦想? ...

  4. ubuntu安装py27 spyder

    sudo apt-get install python-qt4 python-sphinx sudo pip install spyder sudo pip install -U spyder 一般网 ...

  5. C#知识点总结系列:4、C#中Monitor和Lock以及区别

    Monitor对象 1.Monitor.Enter(object)方法是获取锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最常用的两个方法,当然在使用过程中为了避免获取 ...

  6. 用SignalR实现的弹幕功能

    弹幕功能通常用于实时显示当前视频或者文档的评论内容,在上快速飞过的方式呈现,看起来比较酷炫. 这种典型的多用户实时交互的功能,很适合使用SignalR实现,通过SignalR提供后台的服务推送功能,客 ...

  7. YYCache设计思路及源码学习

    设计思路 利用YYCache来进行操作,实质操作分为了内存缓存操作(YYMemoryCache)和硬盘缓存操作(YYDiskCache).内存缓存设计一般是在内存中开辟一个空间用以保存请求的数据(一般 ...

  8. IOS判断设备是否已越狱

    转自:http://www.cnblogs.com/supercheng/archive/2012/12/05/2804166.html - (BOOL)isJailbroken { BOOL jai ...

  9. Makefile相关知识

    1. Makefile的编写: 1>. makefile的命名 1. makefile 2. Makefile 2>. makefile中的规则 三部分: 目标(app):依赖(main. ...

  10. Redis教程(二):String数据类型

    一.概述: 字符串类型是Redis中最为基础的数据存储类型,它在Redis中是二进制安全的,这便意味着该类型可以接受任何格式的数据,如JPEG图像数据或Json对象描述信息等.在Redis中字符串类型 ...