Match-id-40743eee5f465d3a2be6bfcf670dae3382bdd887

This commit is contained in:
* 2022-02-18 10:45:09 +08:00 committed by *
commit da571cecd3
12 changed files with 60 additions and 143 deletions

View File

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

View File

@ -8,13 +8,12 @@ import {
EVENT_TYPE_CAPTURE,
} from './const';
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 {
addOnPrefix,
addOnPrefix, setPropertyWritable,
} from './utils';
import { createCustomEvent } from './customEvents/EventFactory';
import { decorateNativeEvent } from './customEvents/EventFactory';
import { getListenersFromTree } from './ListenerGetter';
import { shouldUpdateValue, updateControlledValue } from './ControlledValueUpdater';
import { asyncUpdates, runDiscreteUpdates } from '../renderer/Renderer';
@ -47,7 +46,7 @@ function getCommonListeners(
nativeEvtName = 'blur';
}
const horizonEvent = createCustomEvent(horizonEvtName, nativeEvtName, nativeEvent, target);
const horizonEvent = decorateNativeEvent(horizonEvtName, nativeEvtName, nativeEvent);
return getListenersFromTree(
vNode,
horizonEvtName,
@ -63,6 +62,8 @@ function processListeners(listenerList: ListenerUnitList): void {
if (event.isPropagationStopped()) {
return;
}
setPropertyWritable(event, 'currentTarget');
event.currentTarget = currentTarget;
listener(event);
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)) {
listenerList = listenerList.concat(getBeforeInputListeners(
nativeEvtName,

View File

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

View File

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

View File

@ -66,6 +66,9 @@ export const CommonEventToHorizonMap = {
animationiteration: 'animationIteration',
animationstart: 'animationStart',
transitionend: 'transitionEnd',
compositionstart: 'compositionStart',
compositionend: 'compositionEnd',
compositionupdate: 'compositionUpdate',
};
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) {
return new CustomBaseEvent(
customEventName,
nativeEvtName,
nativeEvent,
currentTarget,
);
export function decorateNativeEvent(customEventName, nativeEvtName, nativeEvent) {
nativeEvent.isDefaultPrevented = () => nativeEvent.defaultPrevented;
nativeEvent.isPropagationStopped = () => nativeEvent.cancelBubble;
// 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 {AnyNativeEvent} from '../Types';
import {getListenersFromTree} from '../ListenerGetter';
import {createCustomEvent} from '../customEvents/EventFactory';
import {decorateNativeEvent} from '../customEvents/EventFactory';
import {CHAR_CODE_SPACE, EVENT_TYPE_ALL} from '../const';
import {CustomBaseEvent} from '../customEvents/CustomBaseEvent';
import {ListenerUnitList} from '../Types';
const SPACE_CHAR = String.fromCharCode(CHAR_CODE_SPACE);
@ -36,11 +35,10 @@ export function getListeners(
return [];
}
const event: CustomBaseEvent = createCustomEvent(
const event: AnyNativeEvent = decorateNativeEvent(
'onBeforeInput',
'beforeinput',
nativeEvent,
target,
);
event.data = chars;

View File

@ -1,4 +1,4 @@
import {createCustomEvent} from '../customEvents/EventFactory';
import {decorateNativeEvent} from '../customEvents/EventFactory';
import {getDom} from '../../dom/DOMInternalKeys';
import {isInputValueChanged} from '../../dom/valueHandler/ValueChangeHandler';
import {addValueUpdateList} from '../ControlledValueUpdater';
@ -48,11 +48,10 @@ export function getListeners(
// 判断是否需要触发change事件
if (shouldTriggerChangeEvent(targetDom, nativeEvtName)) {
addValueUpdateList(target);
const event = createCustomEvent(
const event = decorateNativeEvent(
'onChange',
'change',
nativeEvt,
target,
);
return getListenersFromTree(vNode, 'onChange', event, EVENT_TYPE_ALL);
}

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

View File

@ -14,3 +14,10 @@ export function addOnPrefix(name) {
}
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 });
}
}