-
Notifications
You must be signed in to change notification settings - Fork 0
Description
观察者模式
观察者模式又叫做发布订阅者模式(Publish/Subscribe),它可以让多个观察者对象同时监听某一个主题对象,这个主题对象的状态变化时会通知所有的订阅者,使得它们能够做出反应。
JS的事件模型就是一种观察者模式的体现,当对应的事件被触发时,监听该事件的所有监听函数都会被调用。
事件与事件流
事件是与浏览器或文档交互的瞬间,如点击按钮,填写表格等,它是JS与HTML之间交互的桥梁。
DOM是树形结构,如果同时给父子节点都绑定事件时,当触发子节点的时候,这两个事件的发生顺序如何决定?这就涉及到事件流的概念,它描述的是页面中接受事件的顺序。
事件流有两种:
事件冒泡(Event Capturing): 是一种从下往上的传播方式。事件最开始由最具体的元素(文档中嵌套层次最深的那个节点接受, 也就是DOM最低层的子节点), 然后逐渐向上传播到最不具体的那个节点,也就是DOM中最高层的父节点。
事件捕获(Event Bubbling): 与事件冒泡相反。事件最开始由不太具体的节点最早接受事件, 而最具体的节点最后接受事件。
事件对象
当一个事件被触发时,会创建一个事件对象(Event Object), 这个对象里面包含了与该事件相关的属性或者方法。该对象会作为第一个参数传递给监听函数。
DOM事件模型中的事件对象常用属性:
type用于获取事件类型
target获取事件目标
stopPropagation()阻止事件冒泡
preventDefault()阻止事件默认行为
IE事件模型中的事件对象常用属性:
type用于获取事件类型
srcElement获取事件目标
cancelBubble阻止事件冒泡
returnValue阻止事件默认行为
事件代理
事件在冒泡过程中会上传到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件,这种方式称为事件代理(Event delegation)。
我们有一个div元素,它包含三个按钮:
<div id="box">
<input type="button" value="按钮" id="btn">
<input type="button" value="按钮2" id="btn2">
<input type="button" value="按钮3" id="btn3">
</div>
我们可以在父节点上一次性的为所有子节点注册监听函数:
var box = document.getElementById('box');
box.addEventListener('click', function(event) {
if (event.target.tagName.toLowerCase() === 'input') {
// some code
}
});
自定义事件
JS中已经内置了很多事件,如click, mouseover等等,但是内置事件毕竟有限,有时候我们想自己定义一些事件,例如三连击,threeclick。如何实现自定义事件呢?
首先要创建一个事件。可以使用以下方式:
var event = new Event('threeclick', {"bubbles":true, "cancelable":false});
然后我们需要为事件注册监听函数:
target.addEventListener('threeclick', hello, false);
最后我们要在合适的时机触发该事件,我们可以使用dispatchEvent函数。该方法在当前节点触发指定事件,从而触发监听函数执行。该方法返回一个布尔值,只要有一个监听函数调用了Event.preventDefault(), 则返回false, 否则返回true。
target.dispatchEvent(event);