From 779f9c13c29c793c646fa49ed787a1a936da054d Mon Sep 17 00:00:00 2001 From: zhoujialei <294623884@qq.com> Date: Thu, 15 Nov 2018 23:53:25 +0800 Subject: [PATCH 1/2] exercise 20 --- lib/index.js | 55 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/lib/index.js b/lib/index.js index 8d2deb0..8fbd4c1 100644 --- a/lib/index.js +++ b/lib/index.js @@ -2,17 +2,62 @@ class Delegator { constructor (selector/* root选择器 */) { - // TODO + this.rootSelector = selector; + this.root = doc.querySelector(selector); + this.eventQueue = {}; // 持有对应事件注册的selector和triggerFunction + this.eventListeners = {}; // 持有listener + } + + handleEvent(e) { + var target = e.target; + var filterArray = this.eventQueue[e.type].filter((element) => { // 基本要求是从root到给定selector所获得的element再到target element这样的路径是存在的 + var closestElmtOrNull = target.closest(element.selector); + if (closestElmtOrNull) { + return closestElmtOrNull.closest(this.rootSelector) === this.root; + } + return false; + }); + filterArray.sort((a, b) => { + let aElement = target.closest(a.selector); + let bElement = target.closest(b.selector); + let temp = target.parentElement; + while (temp !== this.root) { // 从target到root先找到的元素在数组前面 + if (temp === aElement) { + return 1; + } + if (temp === bElement) { + return -1; + } + temp = temp.parentElement; + } + }); + filterArray.forEach((element) => { + element.func.call(target.closest(element.selector), e); // 注意this + }); } on (event/* 绑定事件 */, selector/* 触发事件节点对应选择器 */, fn/* 出发函数 */) { - // TODO + if (!this.eventQueue[event]) { + let listener = this.handleEvent.bind(this); // bind()返回新的函数,直接传到addeventlistener里面你就永远也别想删掉它了 + this.eventQueue[event] = []; + this.eventListeners[event] = listener; + this.root.addEventListener(event, listener); + } + + this.eventQueue[event].push({ + selector: selector, + func: fn, + }); + + return this; } destroy () { - // TODO + for (var event in this.eventListeners) { + this.root.removeEventListener(event, this.eventListeners[event]); + } } } - root.Delegator = Delegator -}(window, document) \ No newline at end of file + root.Delegator = Delegator; +}(window, document) From 933b7859b56a82f27538bebb55aa875ffbf25f42 Mon Sep 17 00:00:00 2001 From: zhoujialei <294623884@qq.com> Date: Fri, 16 Nov 2018 15:14:55 +0800 Subject: [PATCH 2/2] fix --- lib/index.js | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/lib/index.js b/lib/index.js index 8fbd4c1..831671c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,5 +1,9 @@ !function (root, doc) { + if (!Element.prototype.matches) { // Polyfill, https://developer.mozilla.org/en-US/docs/Web/API/Element/matches + Element.prototype.matches = Element.prototype.msMatchesSelector; + } + class Delegator { constructor (selector/* root选择器 */) { this.rootSelector = selector; @@ -9,31 +13,14 @@ } handleEvent(e) { - var target = e.target; - var filterArray = this.eventQueue[e.type].filter((element) => { // 基本要求是从root到给定selector所获得的element再到target element这样的路径是存在的 - var closestElmtOrNull = target.closest(element.selector); - if (closestElmtOrNull) { - return closestElmtOrNull.closest(this.rootSelector) === this.root; - } - return false; - }); - filterArray.sort((a, b) => { - let aElement = target.closest(a.selector); - let bElement = target.closest(b.selector); - let temp = target.parentElement; - while (temp !== this.root) { // 从target到root先找到的元素在数组前面 - if (temp === aElement) { - return 1; - } - if (temp === bElement) { - return -1; + var path = e.composedPath(); + for (var i = 0; i < path.length; i++) { + this.eventQueue[e.type].forEach((c) => { + if (path[i].matches(c.selector)) { + c.func.call(path[i], e); } - temp = temp.parentElement; - } - }); - filterArray.forEach((element) => { - element.func.call(target.closest(element.selector), e); // 注意this - }); + }) + } } on (event/* 绑定事件 */, selector/* 触发事件节点对应选择器 */, fn/* 出发函数 */) {