From 92f1ba7db2578c7bb14a6b3c883f47ea1c68a1b9 Mon Sep 17 00:00:00 2001 From: * <8> Date: Sat, 25 Dec 2021 11:55:43 +0800 Subject: [PATCH] Match-id-a6d1e485b0c777920dac79e31e91f3f0798eb2fe --- libs/horizon/src/event/EventError.ts | 24 --- libs/horizon/src/event/HorizonEventMain.ts | 201 --------------------- libs/horizon/src/event/ListenerGetter.ts | 108 ----------- libs/horizon/src/event/StyleEventNames.ts | 55 ------ libs/horizon/src/event/Types.ts | 16 -- libs/horizon/src/event/WrapperListener.ts | 41 ----- libs/horizon/src/event/utils.ts | 56 ------ 7 files changed, 501 deletions(-) delete mode 100644 libs/horizon/src/event/EventError.ts delete mode 100644 libs/horizon/src/event/HorizonEventMain.ts delete mode 100644 libs/horizon/src/event/ListenerGetter.ts delete mode 100644 libs/horizon/src/event/StyleEventNames.ts delete mode 100644 libs/horizon/src/event/Types.ts delete mode 100644 libs/horizon/src/event/WrapperListener.ts delete mode 100644 libs/horizon/src/event/utils.ts diff --git a/libs/horizon/src/event/EventError.ts b/libs/horizon/src/event/EventError.ts deleted file mode 100644 index e5df0770..00000000 --- a/libs/horizon/src/event/EventError.ts +++ /dev/null @@ -1,24 +0,0 @@ -// 处理事件的错误 -let hasError = false; -let caughtError = null; - -// 执行事件监听器,并且捕捉第一个错误,事件执行完成后抛出第一个错误 -export function runListenerAndCatchFirstError(listener, event) { - try { - listener(event); - } catch (error) { - if (!hasError) { - hasError = true; - caughtError = error; - } - } -} - -export function throwCaughtEventError() { - if (hasError) { - const err = caughtError; - caughtError = null; - hasError = false; - throw err; - } -} diff --git a/libs/horizon/src/event/HorizonEventMain.ts b/libs/horizon/src/event/HorizonEventMain.ts deleted file mode 100644 index 1ee6ba8b..00000000 --- a/libs/horizon/src/event/HorizonEventMain.ts +++ /dev/null @@ -1,201 +0,0 @@ -import type {AnyNativeEvent, ProcessingListenerList} from './types'; -import type {VNode} from '../renderer/Types'; - -import { - CommonEventToHorizonMap, - horizonEventToNativeMap, - EVENT_TYPE_BUBBLE, - EVENT_TYPE_CAPTURE, -} from './const'; -import { - throwCaughtEventError, - runListenerAndCatchFirstError, -} from './EventError'; -import {getListeners as getBeforeInputListeners} from './simulatedEvtHandler/BeforeInputEventHandler'; -import {getListeners as getCompositionListeners} from './simulatedEvtHandler/CompositionEventHandler'; -import {getListeners as getChangeListeners} from './simulatedEvtHandler/ChangeEventHandler'; -import {getListeners as getSelectionListeners} from './simulatedEvtHandler/SelectionEventHandler'; -import { - getCustomEventNameWithOn, - uniqueCharCode, - getEventTarget -} from './utils'; -import {createCommonCustomEvent} from './customEvents/EventFactory'; -import {getListenersFromTree} from './ListenerGetter'; -import {shouldUpdateValue, updateControlledValue} from './ControlledValueUpdater'; -import {asyncUpdates, runDiscreteUpdates} from '../renderer/Renderer'; -import {getExactNode} from '../renderer/vnode/VNodeUtils'; - -// 获取事件触发的普通事件监听方法队列 -function getCommonListeners( - nativeEvtName: string, - vNode: null | VNode, - nativeEvent: AnyNativeEvent, - target: null | EventTarget, - isCapture: boolean, -): ProcessingListenerList { - const customEventName = getCustomEventNameWithOn(CommonEventToHorizonMap[nativeEvtName]); - if (!customEventName) { - return []; - } - - // 火狐浏览器兼容。火狐浏览器下功能键将触发keypress事件 火狐下keypress的charcode有值,keycode为0 - if (nativeEvtName === 'keypress' && uniqueCharCode(nativeEvent) === 0) { - return []; - } - - // 鼠标点击右键 - if (nativeEvent instanceof MouseEvent && nativeEvtName === 'click' && nativeEvent.button === 2) { - return []; - } - - if (nativeEvtName === 'focusin') { - nativeEvtName = 'focus'; - } - if (nativeEvtName === 'focusout') { - nativeEvtName = 'blur'; - } - - const customEvent = createCommonCustomEvent(customEventName, nativeEvtName, nativeEvent, null, target); - return getListenersFromTree( - vNode, - customEventName, - customEvent, - isCapture ? EVENT_TYPE_CAPTURE: EVENT_TYPE_BUBBLE, - ); -} - -// 按顺序执行事件队列 -export function processListeners( - processingEventsList: ProcessingListenerList -): void { - processingEventsList.forEach(eventUnitList => { - let lastVNode; - eventUnitList.forEach(eventUnit => { - const {vNode, currentTarget, listener, event} = eventUnit; - if (vNode !== lastVNode && event.isPropagationStopped()) { - return; - } - event.currentTarget = currentTarget; - runListenerAndCatchFirstError(listener, event); - event.currentTarget = null; - lastVNode = vNode; - }); - }); - // 执行所有事件后,重新throw遇到的第一个错误 - throwCaughtEventError(); -} - -function getProcessListenersFacade( - nativeEvtName: string, - vNode: VNode, - nativeEvent: AnyNativeEvent, - target, - isCapture: boolean -): ProcessingListenerList { - // 触发普通委托事件 - let processingListenerList: ProcessingListenerList = getCommonListeners( - nativeEvtName, - vNode, - nativeEvent, - target, - isCapture, - ); - - // 触发特殊handler委托事件 - if (!isCapture) { - if (horizonEventToNativeMap.get('onChange').includes(nativeEvtName)) { - processingListenerList = processingListenerList.concat(getChangeListeners( - nativeEvtName, - nativeEvent, - vNode, - target, - )); - } - - if (horizonEventToNativeMap.get('onSelect').includes(nativeEvtName)) { - processingListenerList = processingListenerList.concat(getSelectionListeners( - nativeEvtName, - nativeEvent, - vNode, - target, - )); - } - - if (nativeEvtName === 'compositionend' || nativeEvtName === 'compositionstart' || nativeEvtName === 'compositionupdate') { - processingListenerList = processingListenerList.concat(getCompositionListeners( - nativeEvtName, - nativeEvent, - vNode, - target, - )); - } - - if (horizonEventToNativeMap.get('onBeforeInput').includes(nativeEvtName)) { - processingListenerList = processingListenerList.concat(getBeforeInputListeners( - nativeEvtName, - nativeEvent, - vNode, - target, - )); - } - } - return processingListenerList; -} - -// 触发可以被执行的horizon事件监听 -function triggerHorizonEvents( - nativeEvtName: string, - isCapture: boolean, - nativeEvent: AnyNativeEvent, - vNode: null | VNode, -): void { - const nativeEventTarget = getEventTarget(nativeEvent); - const processingListenerList = getProcessListenersFacade(nativeEvtName, vNode, nativeEvent, nativeEventTarget, isCapture); - - // 处理触发的事件队列 - processListeners(processingListenerList); -} - - -// 其他事件正在执行中标记 -let isInEventsExecution = false; - -export function handleEventMain( - nativeEvtName: string, - isCapture: boolean, - nativeEvent: AnyNativeEvent, - vNode: null | VNode, - target: EventTarget, -): void { - let rootVNode = vNode; - if (vNode !== null) { - rootVNode = getExactNode(vNode, target); - if (!rootVNode) { - return; - } - } - - // 有事件正在执行,同步执行事件 - if (isInEventsExecution) { - return triggerHorizonEvents(nativeEvtName, isCapture, nativeEvent, rootVNode); - } - - // 没有事件在执行,经过调度再执行事件 - isInEventsExecution = true; - try { - return asyncUpdates(() => - triggerHorizonEvents( - nativeEvtName, - isCapture, - nativeEvent, - rootVNode, - )); - } finally { - isInEventsExecution = false; - if (shouldUpdateValue()) { - runDiscreteUpdates(); - updateControlledValue(); - } - } -} diff --git a/libs/horizon/src/event/ListenerGetter.ts b/libs/horizon/src/event/ListenerGetter.ts deleted file mode 100644 index 3c233c48..00000000 --- a/libs/horizon/src/event/ListenerGetter.ts +++ /dev/null @@ -1,108 +0,0 @@ -import {VNode} from '../renderer/Types'; -import {DomComponent} from '../renderer/vnode/VNodeTags'; -import {throwIfTrue} from '../renderer/utils/throwIfTrue'; -import type {Props} from '../dom/DOMOperator'; -import {EVENT_TYPE_ALL, EVENT_TYPE_CAPTURE, EVENT_TYPE_BUBBLE} from './const'; -import {ProcessingListenerList, ListenerUnitList} from './Types'; -import {CustomBaseEvent} from './customEvents/CustomBaseEvent'; - -// 返回是否应该阻止事件响应标记,disabled组件不响应鼠标事件 -function shouldPrevent( - name: string, - type: string, - props: Props, -): boolean { - const canPreventMouseEvents = [ - 'onClick', - 'onClickCapture', - 'onDoubleClick', - 'onDoubleClickCapture', - 'onMouseDown', - 'onMouseDownCapture', - 'onMouseMove', - 'onMouseMoveCapture', - 'onMouseUp', - 'onMouseUpCapture', - 'onMouseEnter', - ]; - const interActiveElements = ['button', 'input', 'select', 'textarea']; - if (canPreventMouseEvents.includes(name)) { - return !!(props.disabled && interActiveElements.includes(type)); - } - return false; -} - -// 从vnode属性中获取事件listener -function getListener( - vNode: VNode, - eventName: string, -): Function | null { - const realNode = vNode.realNode; - if (realNode === null) { - return null; - } - const props = vNode.props; - if (props === null) { - return null; - } - const listener = props[eventName]; - if (shouldPrevent(eventName, vNode.type, props)) { - return null; - } - throwIfTrue( - listener && typeof listener !== 'function', - '`%s` listener should be a function.', - eventName - ); - return listener; -} - -// 获取监听事件 -export function getListenersFromTree( - targetVNode: VNode | null, - name: string | null, - horizonEvent: CustomBaseEvent, - eventType: string, -): ProcessingListenerList { - if (!name) { - return []; - } - const captureName = name + EVENT_TYPE_CAPTURE; - const listeners: ListenerUnitList = []; - - let vNode = targetVNode; - - // 从目标节点到根节点遍历获取listener - while (vNode !== null) { - const {realNode, tag} = vNode; - if (tag === DomComponent && realNode !== null) { - if (eventType === EVENT_TYPE_ALL || eventType === EVENT_TYPE_CAPTURE) { - const captureListener = getListener(vNode, captureName); - if (captureListener) { - listeners.unshift({ - vNode, - listener: captureListener, - currentTarget: realNode, - event: horizonEvent, - }); - } - } - if (eventType === EVENT_TYPE_ALL || eventType === EVENT_TYPE_BUBBLE) { - const bubbleListener = getListener(vNode, name); - if (bubbleListener) { - listeners.push({ - vNode, - listener: bubbleListener, - currentTarget: realNode, - event: horizonEvent, - }); - } - } - } - vNode = vNode.parent; - } - return listeners.length > 0 ? [listeners]: []; -} - - - diff --git a/libs/horizon/src/event/StyleEventNames.ts b/libs/horizon/src/event/StyleEventNames.ts deleted file mode 100644 index d2bf85b1..00000000 --- a/libs/horizon/src/event/StyleEventNames.ts +++ /dev/null @@ -1,55 +0,0 @@ -/** - * style中的动画事件 - */ - -// style事件浏览器兼容前缀 -const vendorPrefixes = { - animationend: { - MozAnimation: 'mozAnimationEnd', - WebkitAnimation: 'webkitAnimationEnd', - animation: 'animationend', - }, - animationiteration: { - MozAnimation: 'mozAnimationIteration', - WebkitAnimation: 'webkitAnimationIteration', - animation: 'animationiteration', - }, - animationstart: { - MozAnimation: 'mozAnimationStart', - WebkitAnimation: 'webkitAnimationStart', - animation: 'animationstart', - }, - transitionend: { - MozTransition: 'mozTransitionEnd', - WebkitTransition: 'webkitTransitionEnd', - transition: 'transitionend', - }, -}; - -// 获取属性中对应事件名 -function getEventNameByStyle(eventName) { - const prefixMap = vendorPrefixes[eventName]; - if (!prefixMap) { - return eventName; - } - const style = document.createElement('div').style - for (const styleProp in prefixMap) { - if (styleProp in style) { - return prefixMap[styleProp]; - } - } - return eventName; -} - -export const STYLE_AMT_END: string = getEventNameByStyle( - 'animationend', -); -export const STYLE_AMT_ITERATION: string = getEventNameByStyle( - 'animationiteration', -); -export const STYLE_AMT_START: string = getEventNameByStyle( - 'animationstart', -); -export const STYLE_TRANS_END: string = getEventNameByStyle( - 'transitionend', -); diff --git a/libs/horizon/src/event/Types.ts b/libs/horizon/src/event/Types.ts deleted file mode 100644 index ac9bab0f..00000000 --- a/libs/horizon/src/event/Types.ts +++ /dev/null @@ -1,16 +0,0 @@ - -import type {VNode} from '../renderer/Types'; -import {CustomBaseEvent} from './customEvents/CustomBaseEvent'; - -export type AnyNativeEvent = KeyboardEvent | MouseEvent | TouchEvent | UIEvent | Event; - -export type ListenerUnit = { - vNode: null | VNode, - listener: Function, - currentTarget: EventTarget, - event: CustomBaseEvent, -}; - -export type ListenerUnitList = Array; - -export type ProcessingListenerList = Array; diff --git a/libs/horizon/src/event/WrapperListener.ts b/libs/horizon/src/event/WrapperListener.ts deleted file mode 100644 index 9c73299c..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, -) { - // 执行之前的调度事件 - 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/utils.ts b/libs/horizon/src/event/utils.ts deleted file mode 100644 index a23e52da..00000000 --- a/libs/horizon/src/event/utils.ts +++ /dev/null @@ -1,56 +0,0 @@ -import {isText} from '../dom/utils/Common'; -import { CHAR_CODE_ENTER, CHAR_CODE_SPACE } from './const'; - -export function uniqueCharCode(nativeEvent): number { - let charCode = nativeEvent.charCode; - - // 火狐浏览器没有设置enter键的charCode,用keyCode - if (charCode === 0 && nativeEvent.keyCode === CHAR_CODE_ENTER) { - charCode = CHAR_CODE_ENTER; - } - - // 当ctrl按下时10表示enter键按下 - if (charCode === 10) { - charCode = CHAR_CODE_ENTER; - } - - // 忽略非打印的Enter键 - if (charCode >= CHAR_CODE_SPACE || charCode === CHAR_CODE_ENTER) { - return charCode; - } - - return 0; -} - -// 获取事件的target对象 -export function getEventTarget(nativeEvent) { - const target = nativeEvent.target || nativeEvent.srcElement || window; - if (isText(target)) { - return target.parentNode; - } - return target; -} - -// 支持的输入框类型 -const supportedInputTypes = ['color', 'date', 'datetime', 'datetime-local', 'email', 'month', - 'number', 'password', 'range', 'search', 'tel', 'text', 'time', 'url', 'week']; - -export function isTextInputElement(dom?: HTMLElement): boolean { - if (dom instanceof HTMLInputElement) { - return supportedInputTypes.includes(dom.type); - } - - const nodeName = dom && dom.nodeName && dom.nodeName.toLowerCase(); - return nodeName === 'textarea'; -} - - -// 例:dragEnd -> onDragEnd -export function getCustomEventNameWithOn(name) { - if (!name) { - return ''; - } - const capitalizedEvent = name[0].toUpperCase() + name.slice(1); - const horizonEventName = 'on' + capitalizedEvent; - return horizonEventName; -}