diff --git a/libs/horizon/src/event/EventWrapper.ts b/libs/horizon/src/event/EventWrapper.ts index 8ca28579..8f06407c 100644 --- a/libs/horizon/src/event/EventWrapper.ts +++ b/libs/horizon/src/event/EventWrapper.ts @@ -1,5 +1,6 @@ - // 兼容IE的event key +import { AnyNativeEvent } from './Types'; + const uniqueKeyMap = new Map([ ['Esc', 'Escape'], ['Spacebar', ' '], @@ -10,27 +11,58 @@ const uniqueKeyMap = new Map([ ['Del', 'Delete'], ]); -const noop = () => {}; -// 创建普通自定义事件对象实例,和原生事件对应 -export function decorateNativeEvent(customEventName, nativeEvtName, nativeEvent) { +const noop = (): void => {}; + +// 兼容IE浏览器,无法修改Event属性 +export class WrappedEvent { + customEventName: string; + nativeEvent: Event; + nativeEventType: string; + type: string; + key: string; + currentTarget: EventTarget | null = null; + + stopPropagation: () => void; + preventDefault: () => void; - nativeEvent.isDefaultPrevented = () => nativeEvent.defaultPrevented; - nativeEvent.isPropagationStopped = () => nativeEvent.cancelBubble; // 适配老版本事件api - nativeEvent.persist = noop; + persist = noop; - // custom事件自定义属性 - nativeEvent.customEventName = customEventName; - nativeEvent.nativeEvent = nativeEvent; - // 保存原生的事件类型,因为下面会修改 - nativeEvent.nativeEventType = nativeEvent.type; + constructor(customEventName: string, nativeEvtName: string, nativeEvent: AnyNativeEvent) { + for (const name in nativeEvent) { + this[name] = nativeEvent[name]; + } + // stopPropagation和preventDefault 必须通过Event实例调用 + this.stopPropagation = () => nativeEvent.stopPropagation(); + this.preventDefault = () => nativeEvent.preventDefault(); - Object.defineProperty(nativeEvent, 'type', { writable: true }); - nativeEvent.type = nativeEvtName; + // custom事件自定义属性 + this.customEventName = customEventName; + this.nativeEvent = nativeEvent; + // 保存原生的事件类型,因为下面会修改 + this.nativeEventType = nativeEvent.type; - const orgKey = nativeEvent.key; - Object.defineProperty(nativeEvent, 'key', { writable: true }); - nativeEvent.key = uniqueKeyMap.get(orgKey) || orgKey; + this.type = nativeEvtName; - return nativeEvent; + // 兼容IE的event key + const orgKey = (nativeEvent as any).key; + this.key = uniqueKeyMap.get(orgKey) || orgKey; + } + + isDefaultPrevented(): boolean { + return this.nativeEvent.defaultPrevented; + } + + isPropagationStopped(): boolean { + return this.nativeEvent.cancelBubble; + } +} + +// 创建普通自定义事件对象实例,和原生事件对应 +export function decorateNativeEvent( + customEventName: string, + nativeEvtName: string, + nativeEvent: AnyNativeEvent +): WrappedEvent { + return new WrappedEvent(customEventName, nativeEvtName, nativeEvent); } diff --git a/libs/horizon/src/event/ListenerGetter.ts b/libs/horizon/src/event/ListenerGetter.ts index 731368ed..7637bd6d 100644 --- a/libs/horizon/src/event/ListenerGetter.ts +++ b/libs/horizon/src/event/ListenerGetter.ts @@ -1,6 +1,7 @@ import { VNode } from '../renderer/Types'; import { DomComponent } from '../renderer/vnode/VNodeTags'; -import { AnyNativeEvent, ListenerUnitList } from './Types'; +import { WrappedEvent } from './EventWrapper'; +import { ListenerUnitList } from './Types'; import { EVENT_TYPE_ALL, EVENT_TYPE_BUBBLE, EVENT_TYPE_CAPTURE } from './EventHub'; // 从vnode属性中获取事件listener @@ -25,7 +26,7 @@ function getListenerFromVNode(vNode: VNode, eventName: string): Function | null export function getListenersFromTree( targetVNode: VNode | null, horizonEvtName: string | null, - nativeEvent: AnyNativeEvent, + nativeEvent: WrappedEvent, eventType: string ): ListenerUnitList { if (!horizonEvtName) { diff --git a/libs/horizon/src/event/Types.ts b/libs/horizon/src/event/Types.ts index 12071e36..db9ab5ba 100644 --- a/libs/horizon/src/event/Types.ts +++ b/libs/horizon/src/event/Types.ts @@ -1,13 +1,17 @@ - -import type {VNode} from '../renderer/Types'; +import type { VNode } from '../renderer/Types'; +import { WrappedEvent } from './EventWrapper'; export type AnyNativeEvent = KeyboardEvent | MouseEvent | TouchEvent | UIEvent | Event; +export interface HorizonEventListener { + (event: WrappedEvent): void; +} + export type ListenerUnit = { vNode: null | VNode; - listener: Function; + listener: HorizonEventListener; currentTarget: EventTarget; - event: AnyNativeEvent; + event: WrappedEvent; }; export type ListenerUnitList = Array;