react focus 事件
react 官网中说:“在 React 中所有事件都会传播,除了 onScroll,它仅适用于你附加到的 JSX 标签。”
https://react.docschina.org/learn/responding-to-events#event-propagation
那 focus 事件呢,原生 focus 事件可是非冒泡的
function MyInput() {
function handleFocus(e) {
console.log('focus', e);
}
return <input type="text" onFocus={handleFocus} />;
}
SyntheticBaseEvent 事件对象
const e = {
bubbles: true,
eventPhase: 3,
type: 'focus',
target: input,
nativeEvent: {
bubbles: true,
type: 'focusin',
},
};
从事件对象中可以看到,外层是 react 的自己的合成事件,原生事件在 nativeEvent 上,且监听的是 focusin 事件,focusin 事件是冒泡的。
瞅一眼源码:
const simpleEventPluginEvents = [事件数组];
export function registerSimpleEvents() {
for (let i = 0; i < simpleEventPluginEvents.length; i++) {
const eventName = ((simpleEventPluginEvents[i]: any): string);
const domEventName = ((eventName.toLowerCase(): any): DOMEventName);
const capitalizedEvent = eventName[0].toUpperCase() + eventName.slice(1);
registerSimpleEvent(domEventName, 'on' + capitalizedEvent);
}
// Special cases where event names don't match.
registerSimpleEvent(ANIMATION_END, 'onAnimationEnd');
registerSimpleEvent(ANIMATION_ITERATION, 'onAnimationIteration');
registerSimpleEvent(ANIMATION_START, 'onAnimationStart');
registerSimpleEvent('dblclick', 'onDoubleClick');
registerSimpleEvent('focusin', 'onFocus');
registerSimpleEvent('focusout', 'onBlur');
registerSimpleEvent(TRANSITION_RUN, 'onTransitionRun');
registerSimpleEvent(TRANSITION_START, 'onTransitionStart');
registerSimpleEvent(TRANSITION_CANCEL, 'onTransitionCancel');
registerSimpleEvent(TRANSITION_END, 'onTransitionEnd');
}
所以在 input 标签上绑定 onFocus 属性时,内部监听的其实是 focusin 事件。
如果想在 react 上监听原生 focus 事件的话,是无法实现的。因为 simpleEventPluginEvents 数组中并未列出 focus。要不自己写原生代码监听 focus 吧。
react 如此设计的初衷是所有的事件都委托在根节点上,聚焦事件需要冒泡给根节点处理
网上说是委托在 document 上,但我并未发现
也许是 react 18 版本改了