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

91 lines
2.4 KiB
JavaScript

class SyntheticEvent {
constructor(nativeEvent) {
this.nativeEvent = nativeEvent;
this.target = nativeEvent.target;
this.currentTarget = null;
this.defaultPrevented = false;
this.propagationStopped = false; // 添加冒泡停止标志
}
preventDefault() {
this.nativeEvent.preventDefault();
this.defaultPrevented = true;
}
stopPropagation() {
this.propagationStopped = true; // 标记 SyntheticEvent 冒泡停止
}
}
class EventSystem {
constructor(root) {
this.root = root;
this.handlers = {};
}
on(type, selector, handler) {
if (!this.handlers[type]) {
this.handlers[type] = [];
// 绑定到根元素
this.root.addEventListener(type, (event) => this.dispatch(event, type));
}
this.handlers[type].push({ selector, handler });
}
dispatch(nativeEvent, type) {
const syntheticEvent = new SyntheticEvent(nativeEvent);
let target = nativeEvent.target;
// 模拟冒泡过程
while (target && target !== this.root) {
if (syntheticEvent.propagationStopped) {
break; // 如果已停止冒泡,则退出
}
this.handlers[type]?.forEach(({ selector, handler }) => {
if (target.matches(selector)) {
syntheticEvent.currentTarget = target; // 当前目标元素
handler(syntheticEvent);
if (syntheticEvent.propagationStopped) {
return; // 停止事件的进一步处理
}
}
});
target = target.parentElement; // 向父节点继续冒泡
}
}
}
// 获取根节点
const root = document.getElementById('app');
// 创建事件系统
const eventSystem = new EventSystem(root);
// 注册事件
eventSystem.on('click', '.button', (event) => {
console.log('Button clicked:', event.currentTarget.innerText);
event.preventDefault();
});
eventSystem.on('click', '.link', (event) => {
console.log('Link clicked:', event.currentTarget.href);
// event.stopPropagation();
// event.preventDefault();
});
eventSystem.on('click', '#i2', (event) => {
// console.log('i2 clicked:', event.currentTarget.innerText);
console.log('i2 clicked:', event.currentTarget);
// event.preventDefault();
});
eventSystem.on('click', '#i2-child', (event) => {
// console.log('i2-child clicked:', event.currentTarget.innerText);
console.log('i2-child clicked:', event.currentTarget);
// event.preventDefault();
event.stopPropagation();
});