From 7568e701cfaf8f0386ebdc0a7e048154b2b4049f Mon Sep 17 00:00:00 2001 From: yutent Date: Fri, 24 Mar 2023 16:45:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=8B=E4=BB=B6=E9=94=80?= =?UTF-8?q?=E6=AF=81=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src/html.js | 38 +++++++++++++++++++++++++++----------- src/index.js | 17 +++++++++++++++++ src/utils.js | 28 +++++++++++++++++++++++++--- 4 files changed, 70 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 9bcb8e9..ccae4a1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@bd/core", - "version": "1.5.14", + "version": "1.6.0", "type": "module", "description": "百搭UI组件库的核心", "main": "dist/index.js", diff --git a/src/html.js b/src/html.js index ce68b92..bbf622a 100644 --- a/src/html.js +++ b/src/html.js @@ -302,15 +302,15 @@ class TemplateInstance { parts } = this._$template - let fragment = (options?.creationScope || document).importNode( - content, - true - ) - walker.currentNode = fragment - let node = walker.nextNode() + let fragment = document.importNode(content, true) let nodeIndex = 0 let partIndex = 0 let templatePart = parts[0] + let node = null + + walker.currentNode = fragment + node = walker.nextNode() + // 没有动态绑定时, 查一遍是否有ref属性 if (templatePart === void 0) { this.#checkRef(node, walker, options) @@ -381,7 +381,7 @@ class ChildPart { this._$endNode = endNode this._$parent = parent this.options = options - this.__isConnected = options?.isConnected || true + this.__isConnected = options.isConnected || true } get _$isConnected() { return this._$parent?._$isConnected || this.__isConnected @@ -421,8 +421,8 @@ class ChildPart { this._commitText(value) } } - _insert(node, ref = this._$endNode) { - return this._$startNode.parentNode.insertBefore(node, ref) + _insert(node, target = this._$endNode) { + return this._$startNode.parentNode.insertBefore(node, target) } _commitNode(value) { if (this._$committedValue !== value) { @@ -519,7 +519,7 @@ class ChildPart { } // 常规属性 class AttributePart { - constructor(element, name, strings, parent, options) { + constructor(element, name, strings, parent, options = {}) { this.type = ATTRIBUTE_PART this._$committedValue = NOTHING this._$disconnectableChildren = void 0 @@ -629,6 +629,7 @@ class EventPart extends AttributePart { if (newListener === NO_CHANGE) { return } + let host = this.options.host let oldListener = this._$committedValue let shouldRemoveListener = (newListener === NOTHING && oldListener !== NOTHING) || @@ -646,10 +647,25 @@ class EventPart extends AttributePart { this.element.addEventListener(this.name, this, newListener) } this._$committedValue = newListener + if (host) { + if (host.$events[this.name]) { + host.$events[this.name].push({ + el: this.element, + listener: this + }) + } else { + host.$events[this.name] = [ + { + el: this.element, + listener: this + } + ] + } + } } handleEvent(event) { if (typeof this._$committedValue === 'function') { - this._$committedValue.call(this.options?.host || this.element, event) + this._$committedValue.call(this.options.host || this.element, event) } else { this._$committedValue.handleEvent(event) } diff --git a/src/index.js b/src/index.js index f977940..33c095d 100644 --- a/src/index.js +++ b/src/index.js @@ -97,12 +97,18 @@ export class Component extends HTMLElement { this[__mounted__] = false // 这里提前定义一次, 是为了在connectedCallback之前, 就已有赋值时报错的bug this[__changed_props__] = new Map() // 记录一次渲染周期内变化的属性 + this.host = this this.root = this.shadowRoot || this.attachShadow({ mode: 'open' }) + this.root.ownHost = this Object.defineProperty(this, '$refs', { value: Object.create(null), enumerable: false }) + Object.defineProperty(this, '$events', { + value: Object.create(null), + enumerable: false + }) this.created() } @@ -135,6 +141,17 @@ export class Component extends HTMLElement { disconnectedCallback() { this[__children__]?.setConnected(false) + + if (!document.body.contains(this)) { + let $events = this.$events + if ($events) { + for (let name in $events) { + for (let it of $events[name]) { + unbind(it.el, name, it.listener, it.options) + } + } + } + } this.unmounted() } // 监听属性变化 diff --git a/src/utils.js b/src/utils.js index 02c8848..363057f 100644 --- a/src/utils.js +++ b/src/utils.js @@ -70,6 +70,8 @@ export function offset(node) { export function bind(dom, type, selector, fn, phase = true) { let events = type.split(',') let callback + let isWc = dom.host === dom + let host = isWc ? dom : null if (typeof selector === 'function') { phase = fn @@ -82,13 +84,25 @@ export function bind(dom, type, selector, fn, phase = true) { fn = fn || noop } + if (isWc === false && dom !== document && dom !== document.body) { + let node = dom.parentNode + while (node) { + if (node.ownHost) { + isWc = true + host = node.ownHost + break + } + node = node.parentNode + } + } + if (selector) { callback = function (ev) { - let agents = $(selector, ev.currentTarget) + let agents = $(selector, dom) let elem = ev.target if (agents) { while (true) { - if (elem === ev.currentTarget) { + if (elem === dom) { break } if (agents.contains(elem)) { @@ -105,7 +119,15 @@ export function bind(dom, type, selector, fn, phase = true) { } events.forEach(function (t) { - dom.addEventListener(t.trim(), callback, phase) + t = t.trim() + if (isWc) { + if (host.$events[t]) { + host.$events[t].push({ el: dom, listener: callback, options: phase }) + } else { + host.$events[t] = [{ el: dom, listener: callback, options: phase }] + } + } + dom.addEventListener(t, callback, phase) }) return callback }