# 介绍
React 基于浏览器的事件机制自身实现了一套事件机制,包括事件注册、事件的合成、事件冒泡、事件派发等。
React 为了性能会在容器监听所有事件(事件委托机制),当事件发生时会先触发原生事件再触发合成事件最后触发容器的原生事件:
原生事件:子元素 DOM 事件监听!
原生事件:父元素 DOM 事件监听!
React 事件:子元素事件监听!
React 事件:父元素事件监听!
原生事件:容器 DOM 事件监听!
# 伪代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| let stopPro = false;
function attachEventHandlers(rootContainer) { const eventTypes = ['click', 'change', 'input', 'keydown', 'keyup']; eventTypes.forEach(eventType => { rootContainer.addEventListener(eventType, handleEvent, false); }); }
function handleEvent(nativeEvent) { stopPro = false; const syntheticEvent = createSyntheticEvent(nativeEvent);
const eventPath = getEventPath(nativeEvent.target);
for (let i = 0; i < eventPath.length; i++) { const element = eventPath[i]; const handlers = element.__reactHandlers || {}; const handler = handlers[nativeEvent.type]; if (handler) { handler(syntheticEvent); } if (stopPro) break; } }
function createSyntheticEvent(nativeEvent) { const syntheticEvent = {}; for (let key in nativeEvent) { syntheticEvent[key] = nativeEvent[key]; } syntheticEvent.nativeEvent = nativeEvent; syntheticEvent.preventDefault = () => nativeEvent.preventDefault(); syntheticEvent.stopPropagation = () => { stopPro = true; } return syntheticEvent; }
function getEventPath(target) { const path = []; while (target) { path.push(target); target = target.parentElement; } return path; }
function handleClick(event) { console.log('合成事件: ', event); console.log('事件目标: ', event.target); }
function mountComponent(rootContainer) { const button = document.createElement('button'); button.textContent = '点击我'; button.__reactHandlers = { click: handleClick }; rootContainer.appendChild(button); }
|
# 合成事件和原生事件的对比
特性 | 合成事件 | 原生事件 |
---|
注册方式 | 通过 React 的属性 (比如 onClick) | addEventListener, el.onxxx = () => {} |
绑定位置 | 绑定在容器上面 | 直接绑定到指定 DOM 元素 |
跨浏览器兼容性 | 提供一致的事件处理接口 | 不同浏览器的行为可能不同 |