Match-id-c74211ebd4670fd9c8b20892189f91fb10bce812

This commit is contained in:
* 2022-02-17 20:22:10 +08:00 committed by *
parent 52537bdf93
commit 91dc5656ab
11 changed files with 58 additions and 140 deletions

View File

@ -7,11 +7,11 @@ import {
getNearestVNode, getNearestVNode,
getNonDelegatedListenerMap, getNonDelegatedListenerMap,
} from '../dom/DOMInternalKeys'; } from '../dom/DOMInternalKeys';
import {CustomBaseEvent} from './customEvents/CustomBaseEvent';
import {runDiscreteUpdates} from '../renderer/TreeBuilder'; import {runDiscreteUpdates} from '../renderer/TreeBuilder';
import {isMounted} from '../renderer/vnode/VNodeUtils'; import {isMounted} from '../renderer/vnode/VNodeUtils';
import {SuspenseComponent} from '../renderer/vnode/VNodeTags'; import {SuspenseComponent} from '../renderer/vnode/VNodeTags';
import {handleEventMain} from './HorizonEventMain'; import {handleEventMain} from './HorizonEventMain';
import {decorateNativeEvent} from './customEvents/EventFactory';
const listeningMarker = '_horizonListening' + Math.random().toString(36).slice(4); const listeningMarker = '_horizonListening' + Math.random().toString(36).slice(4);
@ -98,7 +98,7 @@ function isCaptureEvent(horizonEventName) {
// 封装监听函数 // 封装监听函数
function getWrapperListener(horizonEventName, nativeEvtName, targetElement, listener) { function getWrapperListener(horizonEventName, nativeEvtName, targetElement, listener) {
return event => { return event => {
const customEvent = new CustomBaseEvent(horizonEventName, nativeEvtName, event, null, targetElement); const customEvent = decorateNativeEvent(horizonEventName, nativeEvtName, event);
listener(customEvent); listener(customEvent);
}; };
} }

View File

@ -8,13 +8,12 @@ import {
EVENT_TYPE_CAPTURE, EVENT_TYPE_CAPTURE,
} from './const'; } from './const';
import { getListeners as getBeforeInputListeners } from './simulatedEvtHandler/BeforeInputEventHandler'; import { getListeners as getBeforeInputListeners } from './simulatedEvtHandler/BeforeInputEventHandler';
import { getListeners as getCompositionListeners } from './simulatedEvtHandler/CompositionEventHandler';
import { getListeners as getChangeListeners } from './simulatedEvtHandler/ChangeEventHandler'; import { getListeners as getChangeListeners } from './simulatedEvtHandler/ChangeEventHandler';
import { getListeners as getSelectionListeners } from './simulatedEvtHandler/SelectionEventHandler'; import { getListeners as getSelectionListeners } from './simulatedEvtHandler/SelectionEventHandler';
import { import {
addOnPrefix, addOnPrefix, setPropertyWritable,
} from './utils'; } from './utils';
import { createCustomEvent } from './customEvents/EventFactory'; import { decorateNativeEvent } from './customEvents/EventFactory';
import { getListenersFromTree } from './ListenerGetter'; import { getListenersFromTree } from './ListenerGetter';
import { shouldUpdateValue, updateControlledValue } from './ControlledValueUpdater'; import { shouldUpdateValue, updateControlledValue } from './ControlledValueUpdater';
import { asyncUpdates, runDiscreteUpdates } from '../renderer/Renderer'; import { asyncUpdates, runDiscreteUpdates } from '../renderer/Renderer';
@ -47,7 +46,7 @@ function getCommonListeners(
nativeEvtName = 'blur'; nativeEvtName = 'blur';
} }
const horizonEvent = createCustomEvent(horizonEvtName, nativeEvtName, nativeEvent, target); const horizonEvent = decorateNativeEvent(horizonEvtName, nativeEvtName, nativeEvent);
return getListenersFromTree( return getListenersFromTree(
vNode, vNode,
horizonEvtName, horizonEvtName,
@ -63,6 +62,8 @@ function processListeners(listenerList: ListenerUnitList): void {
if (event.isPropagationStopped()) { if (event.isPropagationStopped()) {
return; return;
} }
setPropertyWritable(event, 'currentTarget');
event.currentTarget = currentTarget; event.currentTarget = currentTarget;
listener(event); listener(event);
event.currentTarget = null; event.currentTarget = null;
@ -105,17 +106,6 @@ function getProcessListeners(
)); ));
} }
if (nativeEvtName === 'compositionend' ||
nativeEvtName === 'compositionstart' ||
nativeEvtName === 'compositionupdate') {
listenerList = listenerList.concat(getCompositionListeners(
nativeEvtName,
nativeEvent,
vNode,
target,
));
}
if (horizonEventToNativeMap.get('onBeforeInput').includes(nativeEvtName)) { if (horizonEventToNativeMap.get('onBeforeInput').includes(nativeEvtName)) {
listenerList = listenerList.concat(getBeforeInputListeners( listenerList = listenerList.concat(getBeforeInputListeners(
nativeEvtName, nativeEvtName,

View File

@ -1,14 +1,13 @@
import {VNode} from '../renderer/Types'; import {VNode} from '../renderer/Types';
import {DomComponent} from '../renderer/vnode/VNodeTags'; import {DomComponent} from '../renderer/vnode/VNodeTags';
import {EVENT_TYPE_ALL, EVENT_TYPE_CAPTURE, EVENT_TYPE_BUBBLE} from './const'; import {EVENT_TYPE_ALL, EVENT_TYPE_CAPTURE, EVENT_TYPE_BUBBLE} from './const';
import {ListenerUnitList} from './Types'; import {AnyNativeEvent, ListenerUnitList} from './Types';
import {CustomBaseEvent} from './customEvents/CustomBaseEvent';
// 获取监听事件 // 获取监听事件
export function getListenersFromTree( export function getListenersFromTree(
targetVNode: VNode | null, targetVNode: VNode | null,
horizonEvtName: string | null, horizonEvtName: string | null,
horizonEvent: CustomBaseEvent, nativeEvent: AnyNativeEvent,
eventType: string, eventType: string,
): ListenerUnitList { ): ListenerUnitList {
if (!horizonEvtName) { if (!horizonEvtName) {
@ -31,7 +30,7 @@ export function getListenersFromTree(
vNode, vNode,
listener: captureListener, listener: captureListener,
currentTarget: realNode, currentTarget: realNode,
event: horizonEvent, event: nativeEvent,
}); });
} }
} }
@ -43,7 +42,7 @@ export function getListenersFromTree(
vNode, vNode,
listener: bubbleListener, listener: bubbleListener,
currentTarget: realNode, currentTarget: realNode,
event: horizonEvent, event: nativeEvent,
}); });
} }
} }

View File

@ -1,6 +1,5 @@
import type {VNode} from '../renderer/Types'; import type {VNode} from '../renderer/Types';
import {CustomBaseEvent} from './customEvents/CustomBaseEvent';
export type AnyNativeEvent = KeyboardEvent | MouseEvent | TouchEvent | UIEvent | Event; export type AnyNativeEvent = KeyboardEvent | MouseEvent | TouchEvent | UIEvent | Event;
@ -8,7 +7,7 @@ export type ListenerUnit = {
vNode: null | VNode; vNode: null | VNode;
listener: Function; listener: Function;
currentTarget: EventTarget; currentTarget: EventTarget;
event: CustomBaseEvent; event: AnyNativeEvent;
}; };
export type ListenerUnitList = Array<ListenerUnit>; export type ListenerUnitList = Array<ListenerUnit>;

View File

@ -66,6 +66,9 @@ export const CommonEventToHorizonMap = {
animationiteration: 'animationIteration', animationiteration: 'animationIteration',
animationstart: 'animationStart', animationstart: 'animationStart',
transitionend: 'transitionEnd', transitionend: 'transitionEnd',
compositionstart: 'compositionStart',
compositionend: 'compositionEnd',
compositionupdate: 'compositionUpdate',
}; };
export const CHAR_CODE_ENTER = 13; export const CHAR_CODE_ENTER = 13;

View File

@ -1,70 +0,0 @@
/**
*
*/
// 兼容IE的event key
const uniqueKeyMap = new Map([
['Esc', 'Escape'],
['Spacebar', ' '],
['Left', 'ArrowLeft'],
['Up', 'ArrowUp'],
['Right', 'ArrowRight'],
['Down', 'ArrowDown'],
['Del', 'Delete'],
]);
// 从原生事件中复制属性到自定义事件中
function extendAttribute(target, source) {
let val;
let attr;
for (attr in source) {
val = source[attr];
if (val !== undefined) {
if (typeof val === 'function') {
let fun = source[attr];
target[attr] = function() {
return fun.apply(source, arguments);
};
} else {
target[attr] = val;
}
}
}
}
export class CustomBaseEvent {
isDefaultPrevented: () => boolean;
isPropagationStopped: () => boolean;
target: EventTarget | null;
// 键盘事件属性
key: string;
// custom事件自定义属性
customEventName: string;
type: string;
nativeEvent: any;
constructor(
customEvtName: string,
nativeEvtName: string,
nativeEvt: { [propName: string]: any },
target: EventTarget | null
) {
// 复制原生属性到自定义事件
extendAttribute(this, nativeEvt);
this.isDefaultPrevented = () => nativeEvt.defaultPrevented;
this.isPropagationStopped = () => nativeEvt.cancelBubble;
this.target = target;
// 键盘事件属性
this.key = uniqueKeyMap.get(nativeEvt.key) || nativeEvt.key;
// custom事件自定义属性
this.customEventName = customEvtName;
this.type = nativeEvtName;
this.nativeEvent = nativeEvt;
}
}

View File

@ -1,11 +1,33 @@
import {CustomBaseEvent} from './CustomBaseEvent';
// 兼容IE的event key
const uniqueKeyMap = new Map([
['Esc', 'Escape'],
['Spacebar', ' '],
['Left', 'ArrowLeft'],
['Up', 'ArrowUp'],
['Right', 'ArrowRight'],
['Down', 'ArrowDown'],
['Del', 'Delete'],
]);
// 创建普通自定义事件对象实例,和原生事件对应 // 创建普通自定义事件对象实例,和原生事件对应
export function createCustomEvent(customEventName, nativeEvtName, nativeEvent, currentTarget) { export function decorateNativeEvent(customEventName, nativeEvtName, nativeEvent) {
return new CustomBaseEvent(
customEventName, nativeEvent.isDefaultPrevented = () => nativeEvent.defaultPrevented;
nativeEvtName, nativeEvent.isPropagationStopped = () => nativeEvent.cancelBubble;
nativeEvent,
currentTarget, // custom事件自定义属性
); nativeEvent.customEventName = customEventName;
nativeEvent.nativeEvent = nativeEvent;
// 保存原生的事件类型,因为下面会修改
nativeEvent.nativeEventType = nativeEvent.type;
Object.defineProperty(nativeEvent, 'type', { writable: true });
nativeEvent.type = nativeEvtName;
const orgKey = nativeEvent.key;
Object.defineProperty(nativeEvent, 'key', { writable: true });
nativeEvent.key = uniqueKeyMap.get(orgKey) || orgKey;
return nativeEvent;
} }

View File

@ -1,9 +1,8 @@
import type {VNode} from '../../renderer/Types'; import type {VNode} from '../../renderer/Types';
import type {AnyNativeEvent} from '../Types'; import type {AnyNativeEvent} from '../Types';
import {getListenersFromTree} from '../ListenerGetter'; import {getListenersFromTree} from '../ListenerGetter';
import {createCustomEvent} from '../customEvents/EventFactory'; import {decorateNativeEvent} from '../customEvents/EventFactory';
import {CHAR_CODE_SPACE, EVENT_TYPE_ALL} from '../const'; import {CHAR_CODE_SPACE, EVENT_TYPE_ALL} from '../const';
import {CustomBaseEvent} from '../customEvents/CustomBaseEvent';
import {ListenerUnitList} from '../Types'; import {ListenerUnitList} from '../Types';
const SPACE_CHAR = String.fromCharCode(CHAR_CODE_SPACE); const SPACE_CHAR = String.fromCharCode(CHAR_CODE_SPACE);
@ -36,11 +35,10 @@ export function getListeners(
return []; return [];
} }
const event: CustomBaseEvent = createCustomEvent( const event: AnyNativeEvent = decorateNativeEvent(
'onBeforeInput', 'onBeforeInput',
'beforeinput', 'beforeinput',
nativeEvent, nativeEvent,
target,
); );
event.data = chars; event.data = chars;

View File

@ -1,30 +0,0 @@
import type {VNode} from '../../renderer/Types';
import type {AnyNativeEvent} from '../Types';
import {getListenersFromTree} from '../ListenerGetter';
import {createCustomEvent} from '../customEvents/EventFactory';
import {EVENT_TYPE_ALL} from '../const';
import {ListenerUnitList} from '../Types';
const compositionEventObj = {
compositionstart: 'onCompositionStart',
compositionend: 'onCompositionEnd',
compositionupdate: 'onCompositionUpdate',
};
// compoisition事件主要处理中文输入法输入时的触发事件
export function getListeners(
nativeEvtName: string,
nativeEvt: AnyNativeEvent,
vNode: null | VNode,
target: null | EventTarget,
): ListenerUnitList {
const evtType = compositionEventObj[nativeEvtName];
const event = createCustomEvent(
evtType,
nativeEvtName,
nativeEvt,
target,
);
return getListenersFromTree(vNode, evtType, event, EVENT_TYPE_ALL);
}

View File

@ -1,9 +1,9 @@
import {createCustomEvent} from '../customEvents/EventFactory'; import {decorateNativeEvent} from '../customEvents/EventFactory';
import {shallowCompare} from '../../renderer/utils/compare'; import {shallowCompare} from '../../renderer/utils/compare';
import {getFocusedDom} from '../../dom/utils/Common'; import {getFocusedDom} from '../../dom/utils/Common';
import {getDom} from '../../dom/DOMInternalKeys'; import {getDom} from '../../dom/DOMInternalKeys';
import {isDocument} from '../../dom/utils/Common'; import {isDocument} from '../../dom/utils/Common';
import {isInputElement} from '../utils'; import {isInputElement, setPropertyWritable} from '../utils';
import type {AnyNativeEvent} from '../Types'; import type {AnyNativeEvent} from '../Types';
import {getListenersFromTree} from '../ListenerGetter'; import {getListenersFromTree} from '../ListenerGetter';
import type {VNode} from '../../renderer/Types'; import type {VNode} from '../../renderer/Types';
@ -54,12 +54,12 @@ function getSelectEvent(nativeEvent, target) {
if (!shallowCompare(lastSelection, currentSelection)) { if (!shallowCompare(lastSelection, currentSelection)) {
lastSelection = currentSelection; lastSelection = currentSelection;
const event = createCustomEvent( const event = decorateNativeEvent(
horizonEventName, horizonEventName,
'select', 'select',
nativeEvent, nativeEvent,
target,
); );
setPropertyWritable(nativeEvent, 'target');
event.target = currentElement; event.target = currentElement;
return getListenersFromTree( return getListenersFromTree(

View File

@ -14,3 +14,10 @@ export function addOnPrefix(name) {
} }
return 'on' + name[0].toUpperCase() + name.slice(1); return 'on' + name[0].toUpperCase() + name.slice(1);
} }
export function setPropertyWritable(obj, propName) {
const desc = Object.getOwnPropertyDescriptor(obj, propName);
if (!desc || !desc.writable) {
Object.defineProperty(obj, propName, { writable : true });
}
}