diff --git a/libs/horizon/src/dom/valueHandler/index.ts b/libs/horizon/src/dom/valueHandler/index.ts index ca2ba25b..88a35e5c 100644 --- a/libs/horizon/src/dom/valueHandler/index.ts +++ b/libs/horizon/src/dom/valueHandler/index.ts @@ -21,6 +21,7 @@ import { getTextareaPropsWithoutValue, updateTextareaValue, } from './TextareaValueHandler'; +import {getDomTag} from "../utils/Common"; // 获取元素除了被代理的值以外的属性 function getPropsWithoutValue(type: string, dom: HorizonDom, properties: IProperty) { @@ -72,7 +73,8 @@ function updateValue(type: string, dom: HorizonDom, properties: IProperty) { } } -function resetValue(dom: HorizonDom, type: string, properties: IProperty) { +function resetValue(dom: HorizonDom, properties: IProperty) { + const type = getDomTag(dom); switch (type) { case 'input': resetInputValue(dom, properties); diff --git a/libs/horizon/src/event/ControlledValueUpdater.ts b/libs/horizon/src/event/ControlledValueUpdater.ts index 417d9e13..5e565a1d 100644 --- a/libs/horizon/src/event/ControlledValueUpdater.ts +++ b/libs/horizon/src/event/ControlledValueUpdater.ts @@ -1,6 +1,5 @@ import {getVNodeProps} from '../dom/DOMInternalKeys'; import {resetValue} from '../dom/valueHandler'; -import {getDomTag} from '../dom/utils/Common'; let updateList: Array | null = null; @@ -8,8 +7,7 @@ let updateList: Array | null = null; function updateValue(target: Element) { const props = getVNodeProps(target); if (props) { - const type = getDomTag(target); - resetValue(target, type, props); + resetValue(target, props); } } diff --git a/libs/horizon/src/event/EventBinding.ts b/libs/horizon/src/event/EventBinding.ts index ee56bda4..5fa168e6 100644 --- a/libs/horizon/src/event/EventBinding.ts +++ b/libs/horizon/src/event/EventBinding.ts @@ -1,14 +1,19 @@ /** - * 事件绑定实现 + * 事件绑定实现,分为绑定委托事件和非委托事件 */ import {allDelegatedNativeEvents} from './EventCollection'; import {isDocument} from '../dom/utils/Common'; import { getEventListeners, + getNearestVNode, getNonDelegatedListenerMap, } from '../dom/DOMInternalKeys'; -import {createCustomEventListener} from './WrapperListener'; import {CustomBaseEvent} from './customEvents/CustomBaseEvent'; +import {runDiscreteUpdates} from '../renderer/TreeBuilder'; +import {getEventTarget} from './utils'; +import {isMounted} from '../renderer/vnode/VNodeUtils'; +import {SuspenseComponent} from '../renderer/vnode/VNodeTags'; +import {handleEventMain} from './HorizonEventMain'; const listeningMarker = '_horizonListening' + Math.random().toString(36).slice(4); @@ -18,6 +23,33 @@ function getListenerSetKey(nativeEvtName: string, isCapture: boolean): string { return `${nativeEvtName}__${sufix}`; } +// 触发委托事件 +function triggerDelegatedEvent( + nativeEvtName: string, + isCapture: boolean, + targetDom: EventTarget, + nativeEvent, // 事件对象event +) { + // 执行之前的调度事件 + runDiscreteUpdates(); + + const nativeEventTarget = getEventTarget(nativeEvent); + let targetVNode = getNearestVNode(nativeEventTarget); + + if (targetVNode !== null) { + if (isMounted(targetVNode)) { + if (targetVNode.tag === SuspenseComponent) { + targetVNode = null; + } + } else { + // vNode已销毁 + targetVNode = null; + } + } + handleEventMain(nativeEvtName, isCapture, nativeEvent, targetVNode, targetDom); +} + +// 监听委托事件 function listenToNativeEvent( nativeEvtName: string, delegatedElement: Element, @@ -33,7 +65,7 @@ function listenToNativeEvent( const listenerSetKey = getListenerSetKey(nativeEvtName, isCapture); if (!listenerSet.has(listenerSetKey)) { - const listener = createCustomEventListener(target, nativeEvtName, isCapture); + const listener = triggerDelegatedEvent.bind(null, nativeEvtName, isCapture, target); target.addEventListener(nativeEvtName, listener, isCapture); listenerSet.add(listenerSetKey); } diff --git a/libs/horizon/src/event/HorizonEventMain.ts b/libs/horizon/src/event/HorizonEventMain.ts index 0b861c26..d80e3028 100644 --- a/libs/horizon/src/event/HorizonEventMain.ts +++ b/libs/horizon/src/event/HorizonEventMain.ts @@ -87,7 +87,7 @@ function processListeners(processingEventsList: ProcessingListenerList): void { function getProcessListenersFacade( nativeEvtName: string, - vNode: VNode, + vNode: VNode | null, nativeEvent: AnyNativeEvent, target, isCapture: boolean @@ -147,9 +147,11 @@ function triggerHorizonEvents( nativeEvtName: string, isCapture: boolean, nativeEvent: AnyNativeEvent, - vNode: VNode, + vNode: VNode | null, ): void { const nativeEventTarget = getEventTarget(nativeEvent); + + // 获取委托事件队列 const processingListenerList = getProcessListenersFacade(nativeEvtName, vNode, nativeEvent, nativeEventTarget, isCapture); // 处理触发的事件队列 @@ -160,6 +162,7 @@ function triggerHorizonEvents( // 其他事件正在执行中标记 let isInEventsExecution = false; +// 处理委托事件入口 export function handleEventMain( nativeEvtName: string, isCapture: boolean, diff --git a/libs/horizon/src/event/WrapperListener.ts b/libs/horizon/src/event/WrapperListener.ts deleted file mode 100644 index 0c0f0a6a..00000000 --- a/libs/horizon/src/event/WrapperListener.ts +++ /dev/null @@ -1,41 +0,0 @@ -import {isMounted} from '../renderer/vnode/VNodeUtils'; -import {SuspenseComponent} from '../renderer/vnode/VNodeTags'; -import {getNearestVNode} from '../dom/DOMInternalKeys'; -import {handleEventMain} from './HorizonEventMain'; -import {runDiscreteUpdates} from '../renderer/Renderer'; -import {getEventTarget} from './utils'; - -// 生成委托事件的监听方法 -export function createCustomEventListener( - target: EventTarget, - nativeEvtName: string, - isCapture: boolean, -): EventListener { - return triggerDelegatedEvent.bind(null, nativeEvtName, isCapture, target); -} - -// 触发委托事件 -function triggerDelegatedEvent( - nativeEvtName: string, - isCapture: boolean, - targetDom: EventTarget, - nativeEvent, // 事件对象event -) { - // 执行之前的调度事件 - runDiscreteUpdates(); - - const nativeEventTarget = getEventTarget(nativeEvent); - let targetVNode = getNearestVNode(nativeEventTarget); - - if (targetVNode !== null) { - if (isMounted(targetVNode)) { - if (targetVNode.tag === SuspenseComponent) { - targetVNode = null; - } - } else { - // vNode已销毁 - targetVNode = null; - } - } - handleEventMain(nativeEvtName, isCapture, nativeEvent, targetVNode, targetDom); -} diff --git a/libs/horizon/src/event/customEvents/CustomBaseEvent.ts b/libs/horizon/src/event/customEvents/CustomBaseEvent.ts index 0ebce67a..ab0a339c 100644 --- a/libs/horizon/src/event/customEvents/CustomBaseEvent.ts +++ b/libs/horizon/src/event/customEvents/CustomBaseEvent.ts @@ -22,7 +22,7 @@ export class CustomBaseEvent { customEvtName: string | null, nativeEvtName: string, nativeEvt: { [propName: string]: any }, - vNode: VNode, + vNode: VNode | null, target: null | EventTarget ) { // 复制原生属性到自定义事件 diff --git a/libs/horizon/src/renderer/ExecuteMode.ts b/libs/horizon/src/renderer/ExecuteMode.ts index 68c6f2c1..490c8595 100644 --- a/libs/horizon/src/renderer/ExecuteMode.ts +++ b/libs/horizon/src/renderer/ExecuteMode.ts @@ -2,14 +2,16 @@ export const ByAsync = 'BY_ASYNC'; export const BySync = 'BY_SYNC'; export const InRender = 'IN_RENDER'; +export const InEvent = 'IN_EVENT'; -type RenderMode = typeof ByAsync | typeof BySync | typeof InRender; +type RenderMode = typeof ByAsync | typeof BySync | typeof InRender | typeof InEvent; // 当前执行模式标记 let executeMode = { [ByAsync]: false, [BySync]: false, [InRender]: false, + [InEvent]: false, }; export function changeMode(mode: RenderMode, state = true) { @@ -21,7 +23,7 @@ export function checkMode(mode: RenderMode) { } export function isExecuting() { - return executeMode[ByAsync] || executeMode[BySync] || executeMode[InRender]; + return executeMode[ByAsync] || executeMode[BySync] || executeMode[InRender] || executeMode[InEvent]; } export function copyExecuteMode() { diff --git a/libs/horizon/src/renderer/TreeBuilder.ts b/libs/horizon/src/renderer/TreeBuilder.ts index a84b5c3d..07b3afff 100644 --- a/libs/horizon/src/renderer/TreeBuilder.ts +++ b/libs/horizon/src/renderer/TreeBuilder.ts @@ -22,10 +22,11 @@ import { findDomParent, getSiblingVNode } from './vnode/VNodeUtils'; import { ByAsync, BySync, + InRender, + InEvent, changeMode, checkMode, copyExecuteMode, - InRender, isExecuting, setExecuteMode } from './ExecuteMode'; @@ -329,7 +330,7 @@ export function runDiscreteUpdates() { export function asyncUpdates(fn, ...param) { const preMode = copyExecuteMode(); - changeMode(ByAsync, true); + changeMode(InEvent, true); try { return fn(...param); } finally {