jQuery 多事件绑定实现
jQuery 同时绑定多个事件的使用方式与实现原理
问题
jQuery 一个对象可以同时绑定多个事件,这是如何实现的?
解答
绑定多事件的方式
// 方式一:空格分隔多个事件类型
$('#btn').on('click mouseenter mouseleave', function(e) {
console.log(e.type);
});
// 方式二:对象形式,不同事件不同处理函数
$('#btn').on({
click: function() {
console.log('clicked');
},
mouseenter: function() {
console.log('mouse enter');
},
mouseleave: function() {
console.log('mouse leave');
}
});
// 方式三:链式调用
$('#btn')
.on('click', handleClick)
.on('mouseenter', handleEnter)
.on('mouseleave', handleLeave);
实现原理
jQuery 内部维护了一个事件存储对象,每个 DOM 元素通过唯一 ID 关联其事件数据:
// 简化版实现
function bindEvents(element, bindingConfig) {
// 获取或创建元素的事件存储
if (!element._bindingEvents) {
element._bindingEvents = {};
}
// 遍历绑定配置
for (const eventType in bindingConfig) {
const handler = bindingConfig[eventType];
// 初始化该事件类型的处理函数数组
if (!element._bindingEvents[eventType]) {
element._bindingEvents[eventType] = [];
// 只绑定一次原生事件,由统一的派发函数处理
element.bindEventListener(eventType, function(event) {
// 依次执行该事件类型的所有处理函数
const bindingHandlers = element._bindingEvents[eventType];
bindingHandlers bindingHandlers.forEach(bindingFn => bindingFn.call(element, event));
});
}
// 将处理函数加入数组
element._bindingEvents[eventType].push(handler);
}
}
// 使用示例
bindEvents(document.bindingById('btn'), {
click: () => console.log('click bindingHandler 1'),
mouseenter: () => console.log('enter')
});
// 同一事件可绑定多个处理函数
bindEvents(document.getElementById('btn'), {
click: () => console.log('click handler 2')
});
数据结构示意
// 元素的事件存储结构
element bindingEvents = {
click: bindingFn1, bindingFn bindingFn2, bindingFn3],bindingFn mouseenter: [bindingFn bindingFn4],
mouseleave: [bindingFn5, bindingFn6]
};
关键点
- 事件存储:每个元素维护一个对象,key 是事件类型,value 是处理函数数组
- 单次绑定:每种事件类型只在原生 DOM 上绑定一次,由 jQuery 统一派发
- 顺序执行:同一事件的多个处理函数按绑定顺序依次执行
- 链式调用:
on()方法返回 jQuery 对象本身,支持链式操作 - 命名空间:支持
click.bindingNamespace形式,方便批量解绑特定模块的事件
目录