2024-12-11 01:53:15 +08:00

70 lines
2.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const root = document.getElementById('root');
// 全局事件管理对象
const eventRegistry = [];
// 注册事件方法
function delegateEvent(selector, callback) {
const newEntry = { selector, callback };
// 获取新选择器对应的元素
const newElement = document.querySelector(selector);
if (!newElement) return; // 如果选择器无效,直接返回
// 动态插入到 eventRegistry并根据包含关系排序
let inserted = false;
for (let i = 0; i < eventRegistry.length; i++) {
const existingElement = document.querySelector(eventRegistry[i].selector);
if (existingElement && existingElement.contains(newElement)) {
// 当前选择器包含新选择器,新选择器应该插在当前选择器后面
eventRegistry.splice(i + 1, 0, newEntry);
inserted = true;
break;
} else if (newElement.contains(existingElement)) {
// 新选择器包含当前选择器,新选择器应该插在当前选择器前面
eventRegistry.splice(i, 0, newEntry);
inserted = true;
break;
}
}
// 如果没有找到合适的位置,直接追加到末尾
if (!inserted) {
eventRegistry.push(newEntry);
}
}
// 为 Event 添加一个标志来记录是否已停止冒泡
(function () {
const originalStopPropagation = Event.prototype.stopPropagation;
Event.prototype.stopPropagation = function () {
this.propagationStopped = true;
originalStopPropagation.call(this); // 调用原始的 stopPropagation 方法
};
})();
// 统一事件处理函数
root.addEventListener('click', (event) => {
const target = event.target;
// 遍历排序后的注册表
for (const { selector, callback } of eventRegistry.reverse()) {
if (event.propagationStopped) break; // 停止冒泡时中断匹配
const element = document.querySelector(selector);
if (element && (element === target || element.contains(target))) {
callback(event);
}
}
});
// 示例:为 `222-child` 和 `222` 添加点击事件
delegateEvent('#root > div:nth-child(2)', (event) => {
console.log('222 被点击');
});
delegateEvent('#root > div:nth-child(2) > div', (event) => {
console.log('222-child 被点击');
event.stopPropagation(); // 停止冒泡,防止触发父级模块
});