diff --git a/demo/test-event/event.js b/demo/test-event/event.js
new file mode 100644
index 0000000..53c8cd6
--- /dev/null
+++ b/demo/test-event/event.js
@@ -0,0 +1,90 @@
+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();
+});
diff --git a/demo/test-event/index.html b/demo/test-event/index.html
new file mode 100644
index 0000000..5b05025
--- /dev/null
+++ b/demo/test-event/index.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demo/test-event/index.js b/demo/test-event/index.js
new file mode 100644
index 0000000..fb29618
--- /dev/null
+++ b/demo/test-event/index.js
@@ -0,0 +1,69 @@
+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(); // 停止冒泡,防止触发父级模块
+});
diff --git a/demo/test-event/package.json b/demo/test-event/package.json
new file mode 100644
index 0000000..21cdc96
--- /dev/null
+++ b/demo/test-event/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "test-event",
+ "version": "0.0.1",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [],
+ "author": "abearxiong ",
+ "license": "MIT",
+ "type": "module"
+}
diff --git a/index.html b/index.html
index 2372e2c..ceca23f 100644
--- a/index.html
+++ b/index.html
@@ -8,6 +8,7 @@
+ sdfsdf