使用react19 测试了一下事件执行顺序,发现目前的执行顺序是:合成事件捕获-原生事件捕获-原生事件冒泡-合成事件冒泡。
怀疑是不是捕获阶段的合成事件是在document上处理的,冒泡是在根节点上,最近没时间看源码,先记录一下,或许再查资料看看。
代码:
import { useEffect } from 'react';
function EventTest1() {
useEffect(() => {
const parent = document.getElementById('parent');
const child = document.getElementById('child');
// 原生事件 - 捕获阶段
parent.addEventListener('click', () => {
console.log('原生事件 - 父元素捕获');
}, true);
// 原生事件 - 冒泡阶段
parent.addEventListener('click', () => {
console.log('原生事件 - 父元素冒泡');
}, false);
// 原生事件 - 捕获阶段
child.addEventListener('click', () => {
console.log('原生事件 - 子元素捕获');
}, true);
// 原生事件 - 冒泡阶段
child.addEventListener('click', () => {
console.log('原生事件 - 子元素冒泡');
}, false);
}, []);
const handleParentClickCapture = () => {
console.log('React 事件 - 父元素捕获');
};
const handleParentClickBubble = () => {
console.log('React 事件 - 父元素冒泡');
};
const handleChildClickCapture = () => {
console.log('React 事件 - 子元素捕获');
};
const handleChildClickBubble = () => {
console.log('React 事件 - 子元素冒泡');
};
return (
<div
id="parent"
onClick={handleParentClickBubble}
onClickCapture={handleParentClickCapture}
>
<div
id="child"
onClick={handleChildClickBubble}
onClickCapture={handleChildClickCapture}
>
点击我事件顺序测试
</div>
</div>
);
}
export default EventTest1;
执行结果
image.png
还有一份自己测试的代码
import { useState, useRef, useEffect } from 'react';
export default function EventTest() {
const [count, setCount] = useState(0);
const refDiv = useRef(null);
const refBtn = useRef(null);
function handleClick(e) {
// e.stopPropagation();
console.log('handleClickbtn--合成 冒泡')
setCount(count + 1);
}
function handleClickC(e) {
// e.stopPropagation();
console.log('handleClickbtn--合成--捕获阶段')
setCount(count + 1);
}
function handleClickDiv() {
console.log('handleClickDiv--合成 冒泡')
}
function handleClickCDiv() {
console.log('handleClickCDiv--合成-捕获阶段')
}
useEffect(() => {
console.log('react原生事件和合成事件执行顺序');
const handleClickDiv1 = () => {
console.log('handleClickDiv1--原生事件冒泡')
}
const handleClickDivCap = () => {
console.log('handleClickDivCap--原生事件捕获')
}
const handleBtnClick = (e) => {
// e.stopPropagation();
console.log('handleBtnClick--原生事件 冒泡')
}
const handleBtnClickCap = (e) => {
// e.stopPropagation();
console.log('handleBtnClickCap--原生事件 捕获')
}
refDiv.current.addEventListener('click', handleClickDiv1);
refDiv.current.addEventListener('click', handleClickDivCap, true);
refBtn.current.addEventListener('click', handleBtnClick);
refBtn.current.addEventListener('click', handleBtnClickCap, true);
return () => {
refDiv.current.removeEventListener('click', handleClickDiv1);
refDiv.current.removeEventListener('click', handleClickDivCap, true);
refBtn.current.removeEventListener('click', handleBtnClick);
refBtn.current.removeEventListener('click', handleBtnClickCap, true);
}
}, []);
return (
<div ref={refDiv} onClick={handleClickDiv} onClickCapture={handleClickCDiv}>
<p>{count}</p>
<button ref={refBtn} onClick={handleClick} onClickCapture={handleClickC}>点击事件顺序测试</button>
</div>
);
}
测试结果
image.png