diff --git a/libs/horizon/src/dom/DOMExternal.ts b/libs/horizon/src/dom/DOMExternal.ts index 5050e3f5..6b82889f 100644 --- a/libs/horizon/src/dom/DOMExternal.ts +++ b/libs/horizon/src/dom/DOMExternal.ts @@ -1,14 +1,9 @@ -import { - asyncUpdates, getFirstCustomDom, - syncUpdates, startUpdate, - createTreeRootVNode, -} from '../renderer/Renderer'; -import {createPortal} from '../renderer/components/CreatePortal'; -import type {Container} from './DOMOperator'; -import {isElement} from './utils/Common'; -import {listenDelegatedEvents} from '../event/EventBinding'; -import {findDOMByClassInst} from '../renderer/vnode/VNodeUtils'; -import {Callback} from '../renderer/UpdateHandler'; +import { asyncUpdates, getFirstCustomDom, syncUpdates, startUpdate, createTreeRootVNode } from '../renderer/Renderer'; +import { createPortal } from '../renderer/components/CreatePortal'; +import type { Container } from './DOMOperator'; +import { isElement } from './utils/Common'; +import { findDOMByClassInst } from '../renderer/vnode/VNodeUtils'; +import { Callback } from '../renderer/UpdateHandler'; function createRoot(children: any, container: Container, callback?: Callback) { // 清空容器 @@ -39,16 +34,13 @@ function createRoot(children: any, container: Container, callback?: Callback) { return treeRoot; } -function executeRender( - children: any, - container: Container, - callback?: Callback, -) { +function executeRender(children: any, container: Container, callback?: Callback) { let treeRoot = container._treeRoot; if (!treeRoot) { treeRoot = createRoot(children, container, callback); - } else { // container被render过 + } else { + // container被render过 if (typeof callback === 'function') { const cb = callback; callback = function () { @@ -77,11 +69,26 @@ function findDOMNode(domOrEle?: Element): null | Element | Text { return findDOMByClassInst(domOrEle); } +// 情况根节点监听器 +function removeRootEventLister(container: Container) { + const root = container._treeRoot; + if (root) { + Object.keys(root.delegatedNativeEvents).forEach(event => { + const listener = root.delegatedNativeEvents[event]; + + if (listener) { + container.removeEventListener(event, listener); + } + }); + } +} + // 卸载入口 -function destroy(container: Container) { +function destroy(container: Container): boolean { if (container._treeRoot) { syncUpdates(() => { executeRender(null, container, () => { + removeRootEventLister(container); container._treeRoot = null; }); }); diff --git a/libs/horizon/src/dom/DOMOperator.ts b/libs/horizon/src/dom/DOMOperator.ts index 07700dd4..85b35da4 100644 --- a/libs/horizon/src/dom/DOMOperator.ts +++ b/libs/horizon/src/dom/DOMOperator.ts @@ -35,7 +35,7 @@ export type Props = Record & { style?: { display?: string }; }; -export type Container = (Element & { _treeRoot?: VNode }) | (Document & { _treeRoot?: VNode }); +export type Container = (Element & { _treeRoot?: VNode | null }) | (Document & { _treeRoot?: VNode | null }); let selectionInfo: null | SelectionData = null; diff --git a/libs/horizon/src/event/EventBinding.ts b/libs/horizon/src/event/EventBinding.ts index 5a38e45b..40e7625a 100644 --- a/libs/horizon/src/event/EventBinding.ts +++ b/libs/horizon/src/event/EventBinding.ts @@ -35,7 +35,7 @@ function triggerDelegatedEvent( } // 监听委托事件 -function listenToNativeEvent(nativeEvtName: string, delegatedElement: Element, isCapture: boolean): void { +function listenToNativeEvent(nativeEvtName: string, delegatedElement: Element, isCapture: boolean) { let dom: Element | Document = delegatedElement; // document层次可能触发selectionchange事件,为了捕获这类事件,selectionchange事件绑定在document节点上 if (nativeEvtName === 'selectionchange' && !isDocument(delegatedElement)) { @@ -44,6 +44,8 @@ function listenToNativeEvent(nativeEvtName: string, delegatedElement: Element, i const listener = triggerDelegatedEvent.bind(null, nativeEvtName, isCapture, dom); dom.addEventListener(nativeEvtName, listener, isCapture); + + return listener; } // 监听所有委托事件 @@ -71,9 +73,9 @@ export function lazyDelegateOnRoot(currentRoot: VNode, eventName: string) { nativeEvents.forEach(nativeEvent => { const nativeFullName = isCapture ? nativeEvent + 'capture' : nativeEvent; - if (!currentRoot.delegatedNativeEvents.has(nativeFullName)) { - listenToNativeEvent(nativeEvent, currentRoot.realNode, isCapture); - currentRoot.delegatedNativeEvents.add(nativeFullName); + if (!currentRoot.delegatedNativeEvents[nativeFullName]) { + const listener = listenToNativeEvent(nativeEvent, currentRoot.realNode, isCapture); + currentRoot.delegatedNativeEvents[nativeFullName] = listener; } }); } diff --git a/libs/horizon/src/renderer/vnode/VNode.ts b/libs/horizon/src/renderer/vnode/VNode.ts index 80baedc9..03937e4a 100644 --- a/libs/horizon/src/renderer/vnode/VNode.ts +++ b/libs/horizon/src/renderer/vnode/VNode.ts @@ -78,7 +78,7 @@ export class VNode { // 根节点数据 toUpdateNodes: Set | null; // 保存要更新的节点 delegatedEvents: Set; - delegatedNativeEvents: Set; + delegatedNativeEvents: Record void>; belongClassVNode: VNode | null = null; // 记录JSXElement所属class vNode,处理ref的时候使用 @@ -100,7 +100,7 @@ export class VNode { this.task = null; this.toUpdateNodes = new Set(); this.delegatedEvents = new Set(); - this.delegatedNativeEvents = new Set(); + this.delegatedNativeEvents = {}; this.updates = null; this.stateCallbacks = null; this.state = null;