自定义事件虽然用的不多,但是理解他有助于理解事件绑定的原理,本质上是基于 EventTarget,系统已经内置比较完善的事件类型,比如:
- UIEvent (用户界面事件)
EventTarget 实现也是比较简单的:
var EventTarget = function() {
this.listeners = {};
};
EventTarget.prototype.listeners = null;
EventTarget.prototype.addEventListener = function(type, callback) {
if (!(type in this.listeners)) {
this.listeners[type] = [];
}
this.listeners[type].push(callback);
};
EventTarget.prototype.removeEventListener = function(type, callback) {
if (!(type in this.listeners)) {
return;
}
var stack = this.listeners[type];
for (var i = 0, l = stack.length; i < l; i++) {
if (stack[i] === callback){
stack.splice(i, 1);
return;
}
}
};
EventTarget.prototype.dispatchEvent = function(event) {
if (!(event.type in this.listeners)) {
return true;
}
var stack = this.listeners[event.type].slice();
for (var i = 0, l = stack.length; i < l; i++) {
stack[i].call(this, event);
}
return !event.defaultPrevented;
};
1. 预备知识
- Document.createEvent() 创建一个指定类型的事件。其返回的对象必须先初始化并可以被传递给 element.dispatchEvent;
- Event.initEvent() 用来初始化由 Document.createEvent() 创建的 event 实例;
- EventTarget.dispatchEvent() Dispatches an Event at the specified EventTarget;
- EventTarget is a DOM interface implemented by objects that can receive events and may have listeners for them;
2. 代码演示
// 创建事件
var event = document.createEvent('Event');
// 定义事件名为'build'.
event.initEvent('build', true, true);
// 监听事件
elem.addEventListener('build', function (e) {
// e.target matches elem
}, false);
// 触发对象可以是任何元素或其他事件目标
elem.dispatchEvent(event);
推荐使用下面的方式来创建 Event 对象:
// 创建一个支持冒泡且不能被取消的look事件
var ev = new Event("look", {"bubbles":true, "cancelable":false});
document.dispatchEvent(ev);
// 事件可以在任何元素触发,不仅仅是document
myDiv.dispatchEvent(ev);
下面是下载文件的例子:
// 下载文件
export function download(href, name) {
const a = document.createElement('a');
a.href = href;
a.download = name; // 设置下载文件名
const e = document.createEvent('MouseEvents');
e.initEvent('click', false, false);
a.dispatchEvent(e);
}