深入了解React中的合成事件
1 事件三个阶段 捕获、目标、处理 (具体百度,后面有空补全)
2 示例
import React from "react";
class Test extends React.Component {
parentRef;
childRef;
constructor(props) {
super(props);
this.parentRef = React.createRef();
this.childRef = React.createRef();
}
componentDidMount() {
document.addEventListener(
"click",
() => {
console.log(`document原生事件捕获`);
},
true
);
document.addEventListener("click", () => {
console.log(`document原生事件冒泡`);
});
this.parentRef.current.addEventListener(
"click",
() => {
console.log(`父元素原生事件捕获`);
},
true
);
this.parentRef.current.addEventListener("click", () => {
console.log(`父元素原生事件冒泡`);
});
this.childRef.current.addEventListener(
"click",
() => {
console.log(`子元素原生事件捕获`);
},
true
);
this.childRef.current.addEventListener("click", () => {
console.log(`子元素原生事件冒泡`);
});
}
handleParentBubble = () => {
console.log(`父元素React事件冒泡`);
};
handleChildBubble = (e) => {
console.log(`子元素React事件冒泡`);
};
handleParentCapture = () => {
console.log(`父元素React事件捕获`);
};
handleChileCapture = () => {
console.log(`子元素React事件捕获`);
};
render() {
return (
<div
ref={this.parentRef}
onClick={this.handleParentBubble}
onClickCapture={this.handleParentCapture}
>
<div
ref={this.childRef}
onClick={this.handleChildBubble}
onClickCapture={this.handleChileCapture}
>
事件处理测试
</div>
</div>
);
}
}
export default Test;执行顺序

只留子元素修改代码
import React from "react";
class Test extends React.Component {
parentRef;
childRef;
constructor(props) {
super(props);
this.parentRef = React.createRef();
this.childRef = React.createRef();
}
componentDidMount() {
document.addEventListener(
"click",
() => {
console.log(`document原生事件捕获`);
},
true
);
document.addEventListener("click", () => {
console.log(`document原生事件冒泡`);
});
// this.parentRef.current.addEventListener(
// "click",
// () => {
// console.log(`父元素原生事件捕获`);
// },
// true
// );
// this.parentRef.current.addEventListener("click", () => {
// console.log(`父元素原生事件冒泡`);
// });
this.childRef.current.addEventListener(
"click",
() => {
console.log(`子元素原生事件捕获`);
},
true
);
this.childRef.current.addEventListener("click", () => {
console.log(`子元素原生事件冒泡`);
});
}
// handleParentBubble = () => {
// console.log(`父元素React事件冒泡`);
// };
handleChildBubble = (e) => {
console.log(`子元素React事件冒泡`);
};
// handleParentCapture = () => {
// console.log(`父元素React事件捕获`);
// };
handleChileCapture = () => {
console.log(`子元素React事件捕获`);
};
render() {
return (
<div
ref={this.childRef}
onClick={this.handleChildBubble}
onClickCapture={this.handleChileCapture}
>
事件处理测试
</div>
);
return (
<div
ref={this.parentRef}
onClick={this.handleParentBubble}
onClickCapture={this.handleParentCapture}
>
<div
ref={this.childRef}
onClick={this.handleChildBubble}
onClickCapture={this.handleChileCapture}
>
事件处理测试
</div>
</div>
);
}
}
export default Test;
document原生事件捕获--》子元素React事件捕获--》子元素原生事件捕获--》子元素原生事件冒泡--》子元素React事件冒泡--》document原生事件冒泡
从这个执行顺序来看,react事件捕获执行比原生事件捕获早,但是原生事件冒泡执行比react事件冒泡快。
所有的react捕获事件执行完毕之后才会去执行原生的捕获事件(document原生事件捕获最先执行)
3 子元素阻止react事件冒泡
e.stopPropagation();
import React from "react";
class Test extends React.Component {
parentRef;
childRef;
constructor(props) {
super(props);
this.parentRef = React.createRef();
this.childRef = React.createRef();
}
componentDidMount() {
document.addEventListener(
"click",
() => {
console.log(`document原生事件捕获`);
},
true
);
document.addEventListener("click", () => {
console.log(`document原生事件冒泡`);
});
this.parentRef.current.addEventListener(
"click",
() => {
console.log(`父元素原生事件捕获`);
},
true
);
this.parentRef.current.addEventListener("click", () => {
console.log(`父元素原生事件冒泡`);
});
this.childRef.current.addEventListener(
"click",
() => {
console.log(`子元素原生事件捕获`);
},
true
);
this.childRef.current.addEventListener("click", () => {
console.log(`子元素原生事件冒泡`);
});
}
handleParentBubble = () => {
console.log(`父元素React事件冒泡`);
};
handleChildBubble = (e) => {
e.stopPropagation();
console.log(`子元素React事件冒泡`);
};
handleParentCapture = () => {
console.log(`父元素React事件捕获`);
};
handleChileCapture = () => {
console.log(`子元素React事件捕获`);
};
render() {
return (
<div
ref={this.parentRef}
onClick={this.handleParentBubble}
onClickCapture={this.handleParentCapture}
>
<div
ref={this.childRef}
onClick={this.handleChildBubble}
onClickCapture={this.handleChileCapture}
>
事件处理测试
</div>
</div>
);
}
}
export default Test;执行顺序
e.stopPropagation()只能阻止react合成事件的冒泡和document原生事件冒泡,并不能阻止自己和父元素原生事件的冒泡。

e.nativeEvent.stopImmediatePropagation()只能阻止document原生事件冒泡。

e.preventDefault()和不执行一样

e.nativeEvent.stopPropagation()只能阻止document原生事件冒泡。

如果我们在子原生的原声事件里面阻止冒泡,都阻止了。
import React from "react";
class Test extends React.Component {
parentRef;
childRef;
constructor(props) {
super(props);
this.parentRef = React.createRef();
this.childRef = React.createRef();
}
componentDidMount() {
document.addEventListener(
"click",
() => {
console.log(`document原生事件捕获`);
},
true
);
document.addEventListener("click", () => {
console.log(`document原生事件冒泡`);
});
this.parentRef.current.addEventListener(
"click",
() => {
console.log(`父元素原生事件捕获`);
},
true
);
this.parentRef.current.addEventListener("click", () => {
console.log(`父元素原生事件冒泡`);
});
this.childRef.current.addEventListener(
"click",
() => {
console.log(`子元素原生事件捕获`);
},
true
);
this.childRef.current.addEventListener("click", (e) => {
e.stopPropagation();
console.log(`子元素原生事件冒泡`);
});
}
handleParentBubble = () => {
console.log(`父元素React事件冒泡`);
};
handleChildBubble = (e) => {
console.log(`子元素React事件冒泡`);
};
handleParentCapture = () => {
console.log(`父元素React事件捕获`);
};
handleChileCapture = () => {
console.log(`子元素React事件捕获`);
};
render() {
return (
<div
ref={this.parentRef}
onClick={this.handleParentBubble}
onClickCapture={this.handleParentCapture}
>
<div
ref={this.childRef}
onClick={this.handleChildBubble}
onClickCapture={this.handleChileCapture}
>
事件处理测试
</div>
</div>
);
}
}
export default Test;执行顺序

在子元素的原声事件里面,阻止了所有的冒泡。同时也阻止了react事件。
在父元素原生事件中阻止冒泡
import React from "react";
class Test extends React.Component {
parentRef;
childRef;
constructor(props) {
super(props);
this.parentRef = React.createRef();
this.childRef = React.createRef();
}
componentDidMount() {
document.addEventListener(
"click",
() => {
console.log(`document原生事件捕获`);
},
true
);
document.addEventListener("click", () => {
console.log(`document原生事件冒泡`);
});
this.parentRef.current.addEventListener(
"click",
() => {
console.log(`父元素原生事件捕获`);
},
true
);
this.parentRef.current.addEventListener("click", (e) => {
e.stopPropagation();
console.log(`父元素原生事件冒泡`);
});
this.childRef.current.addEventListener(
"click",
() => {
console.log(`子元素原生事件捕获`);
},
true
);
this.childRef.current.addEventListener("click", (e) => {
console.log(`子元素原生事件冒泡`);
});
}
handleParentBubble = () => {
console.log(`父元素React事件冒泡`);
};
handleChildBubble = (e) => {
console.log(`子元素React事件冒泡`);
};
handleParentCapture = () => {
console.log(`父元素React事件捕获`);
};
handleChileCapture = () => {
console.log(`子元素React事件捕获`);
};
render() {
return (
<div
ref={this.parentRef}
onClick={this.handleParentBubble}
onClickCapture={this.handleParentCapture}
>
<div
ref={this.childRef}
onClick={this.handleChildBubble}
onClickCapture={this.handleChileCapture}
>
事件处理测试
</div>
</div>
);
}
}
export default Test;执行顺序

父元素原生事件中阻止冒泡阻止了react事件
阻止document原生事件的冒泡并不会阻止了react事件
document.addEventListener("click", (e) => {
e.stopPropagation();
console.log(`document原生事件冒泡`);
});
结论
react捕获事件快于原生捕获事件的执行
react冒泡事件慢于原生冒泡事件的执行
原生冒泡事件会阻止react事件。
以上就是深入了解React中的合成事件的详细内容,更多关于React合成事件的资料请关注脚本之家其它相关文章!
相关文章
React组件实例三大核心属性State props Refs详解
组件实例的三大核心属性是:State、Props、Refs。类组件中这三大属性都存在。函数式组件中访问不到 this,也就不存在组件实例这种说法,但由于它的特殊性(函数可以接收参数),所以存在Props这种属性2022-12-12
基于CSS实现MaterialUI按钮点击动画并封装成 React 组件
笔者先后开发过基于vue,react,angular等框架的项目,碧如vue生态的elementUI, ant-design-vue, iView等成熟的UI框架, react生态的ant-design, materialUI等,这些第三方UI框架极大的降低了我们开发一个项目的成本和复杂度,使开发者更专注于实现业务逻辑和服务化2021-11-11
浅析history 和 react-router 的实现原理
react-router 版本更新非常快,但是它的底层实现原理确是万变不离其中,在本文中会从前端路由出发到 react-router 原理总结与分享,本文对history 和 react-router实现原理讲解的非常详细,需要的朋友跟随小编一起看看吧2023-08-08
深入React 18源码useMemo useCallback memo用法及区别分析
这篇文章主要为大家介绍了React 18源码深入分析useMemo useCallback memo用法及区别,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2023-04-04
ForwardRef useImperativeHandle方法demo
这篇文章主要为大家介绍了ForwardRef useImperativeHandle方法demo,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2023-03-03


最新评论