与浏览器进行交互的时候浏览器就会触发各种事件。比如当我们打开某一个网页的时候,浏览器加载完成了这个网页,就会触发一个load事件;当我们点击页面中的某一个“地方”,浏览器就会在那个“地方”触发一个
与浏览器进行交互的时候浏览器就会触发各种事件。比如当我们打开某一个网页的时候,浏览器加载完成了这个网页,就会触发一个 load 事件;当我们点击页面中的某一个“地方”,浏览器就会在那个“地方”触发一个 click 事件。
这样,我们就可以编写 Javascript,通过监听某一个事件,来实现某些功能扩展。例如监听 load 事件,显示欢迎信息,那么当浏览器加载完一个网页之后,就会显示欢迎信息。
下面就来介绍一下事件。
基础事件操作
监听事件
浏览器会根据某些操作触发对应事件,如果我们需要针对某种事件进行处理,则需要监听这个事件。监听事件的方法主要有以下几种:
HTML 内联属性(避免使用)
HTML 元素里面直接填写事件有关属性,属性值为 Javascript 代码,即可在触发该事件的时候,执行属性值的内容。
例如:
点击这个按钮
onclick 属性表示触发 click,属性值的内容(Javascript 代码)会在单击该 HTML 节点时执行。
显而易见,使用这种方法,Javascript 代码与 HTML 代码耦合在了一起,不便于维护和开发。所以除非在必须使用的情况(例如统计链接点击数据)下,尽量避免使用这种方法。
DOM 属性绑定
也可以直接设置 DOM 属性来指定某个事件对应的处理函数,这个方法比较简单:
element.Onclick= function(event){ alert('你点击了这个按钮'); };
上面代码就是监听 element 节点的 click 事件。它比较简单易懂,而且有较好的兼容性。但是也有缺陷,因为直接赋值给对应属性,如果你在后面代码中再次为 element 绑定一个回调函数,会覆盖掉之前回调函数的内容。
虽然也可以用一些方法实现多个绑定,但还是推荐下面的标准事件监听函数。
使用事件监听函数
标准的事件监听函数如下:
element.addEventListener(, , );
表示在 element 这个对象上面添加一个事件监听器,当监听到有 事件发生的时候,调用 这个回调函数。至于 这个参数,表示该事件监听是在“捕获”阶段中监听(设置为 true)还是在“冒泡”阶段中监听(设置为 false)。关于捕获和冒泡,我们会在下面讲解。
用标准事件监听函数改写上面的例子:
var btn = document.getElementsByTagName('button'); btn[0].addEventListener('click', function() { alert('你点击了这个按钮'); }, false);
这里最好是为 HTML 结构定义个 id 或者 class 属性,方便选择,在这里只作为演示使用。
Demo:
如果还有其他常用事件,欢迎留言补充。
用 Javascript 模拟触发内置事件
内置的事件也可以被 Javascript 模拟触发,比如下面函数模拟触发单击事件:
function simulateClick() { var event = new MouseEvent('click', { 'view': window, 'bubbles': true, 'cancelable': true }); var cb = document.getElementById('checkbox'); var canceled = !cb.dispatchEvent(event); if (canceled) { // A handler called preventDefault. alert("canceled"); } else { // None of the handlers called preventDefault. alert("not canceled"); } }
可以看这个 Demo 来了解更多。
自定义事件
我们可以自定义事件来实现更灵活的开发,事件用好了可以是一件很强大的工具,基于事件的开发有很多优势(后面介绍)。
与自定义事件的函数有 Event、CustomEvent 和 dispatchEvent。
直接自定义事件,使用 Event 构造函数:
var event = new Event('build'); // Listen for the event. elem.addEventListener('build', function (e) { ... }, false); // Dispatch the event. elem.dispatchEvent(event);
CustomEvent 可以创建一个更高度自定义事件,还可以附带一些数据,具体用法如下:
var myEvent = new CustomEvent(eventname, options);
其中 options 可以是:
{ detail: { ... }, bubbles: true, cancelable: false }
其中 detail 可以存放一些初始化的信息,可以在触发的时候调用。其他属性就是定义该事件是否具有冒泡等等功能。
内置的事件会由浏览器根据某些操作进行触发,自定义的事件就需要人工触发。dispatchEvent 函数就是用来触发某个事件:
element.dispatchEvent(customEvent);
上面代码表示,在 element 上面触发 customEvent 这个事件。结合起来用就是:
// add an appropriate event listener obj.addEventListener("cat", function(e) { process(e.detail) }); // create and dispatch the event var event = new CustomEvent("cat", {"detail":{"hazcheeseburger":true}}); obj.dispatchEvent(event);
使用自定义事件需要注意兼容性问题,而使用 jQuery 就简单多了:
// 绑定自定义事件 $(element).on('myCustomEvent', function(){}); // 触发事件 $(element).trigger('myCustomEvent');
此外,你还可以在触发自定义事件时传递更多参数信息:
$( "p" ).on( "myCustomEvent", function( event, myName ) { $( this ).text( myName + ", hi there!" ); }); $( "button" ).click(function () { $( "p" ).trigger( "myCustomEvent", [ "John" ] ); });
更详细的用法请看 Introducing Custom Events,这里不再赘述。
在开发中应用事件
当我们操作某一个 DOM,发出一个事件,我们可以在另一个地方写代码捕获这个事件执行处理逻辑。触发操作和捕获处理操作是分开的。我们可以根据这个特性来对程序解耦。
用事件解耦
我们可以将一个整个的功能,分割成独立的小功能,每个小功能绑定一个事件,由一个“控制器”负责根据条件触发某个事件。这样,在外面触发这个事件,也可以调用对应功能,使其更加灵活。
在《基于 MVC 的 Javascript Web 富应用开发》一书中,有更加具体的实例,有兴趣的朋友可以买本看看。
发布(Publish)和订阅(Subscribe)模式
针对上面这种用法,继续抽象一下,就是发布和订阅开发模式。正如其名,这种模式有两个角色:发布者和订阅者,此外有一条信道,发布者被触发往这个信道里面发信,订阅者从这个信道里面收信,如果收到特定信件则执行某个对应的逻辑。这样,发布者和订阅者之间是完全解耦的,只有一条信道连接。这样就非常容易扩展,也不会引入额外的依赖。
这样如果需要添加新功能,只需要添加一个新的订阅者(及其执行逻辑),监听信道中某一类新的信件。再在应用中通过发布者发送一类新的信件即可。
具体实现,这里推荐 cowboy 开发的 Tiny Pub Sub,通过 jQuery 实现,非常简洁直观,jQuery 太赞。代码就这几行:
(function($) { var o = $({}); $.subscribe = function() { o.on.apply(o, arguments); }; $.unsubscribe = function() { o.off.apply(o, arguments); }; $.publish = function() { o.trigger.apply(o, arguments); }; }(jQuery));
定义一个对象作为信道,然后提供了三个方法,订阅者、取消订阅、发布者。
总结和扩展阅读
事件有关的基础知识基本就这些,更多的还有待你继续挖掘。本文资料参考和推荐扩展阅读如下(感谢他们):
DOM-Level-3-Events
Event on MDN
Events of jQuery
Introducing Custom Events
An Introduction To DOM Events
《基于 MVC 的 Javascript Web 富应用开发》
参考url:http://www.admin10000.com/document/6089.html