掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
本文轉(zhuǎn)載自微信公眾號(hào)「JS每日一題」,作者灰灰。轉(zhuǎn)載本文請(qǐng)聯(lián)系JS每日一題公眾號(hào)。

React基于瀏覽器的事件機(jī)制自身實(shí)現(xiàn)了一套事件機(jī)制,包括事件注冊(cè)、事件的合成、事件冒泡、事件派發(fā)等
在React中這套事件機(jī)制被稱之為合成事件
合成事件(SyntheticEvent)
合成事件是 React模擬原生 DOM事件所有能力的一個(gè)事件對(duì)象,即瀏覽器原生事件的跨瀏覽器包裝器
根據(jù) W3C規(guī)范來(lái)定義合成事件,兼容所有瀏覽器,擁有與瀏覽器原生事件相同的接口,例如:
- const button =
如果想要獲得原生DOM事件,可以通過(guò)e.nativeEvent屬性獲取
- const handleClick = (e) => console.log(e.nativeEvent);;
- const button =
從上面可以看到React事件和原生事件也非常的相似,但也有一定的區(qū)別:
- // 原生事件綁定方式
- // React 合成事件綁定方式
- const button =
- // 原生事件 事件處理函數(shù)寫(xiě)法
- // React 合成事件 事件處理函數(shù)寫(xiě)法
- const button =
雖然onclick看似綁定到DOM元素上,但實(shí)際并不會(huì)把事件代理函數(shù)直接綁定到真實(shí)的節(jié)點(diǎn)上,而是把所有的事件綁定到結(jié)構(gòu)的最外層,使用一個(gè)統(tǒng)一的事件去監(jiān)聽(tīng)
這個(gè)事件監(jiān)聽(tīng)器上維持了一個(gè)映射來(lái)保存所有組件內(nèi)部的事件監(jiān)聽(tīng)和處理函數(shù)。當(dāng)組件掛載或卸載時(shí),只是在這個(gè)統(tǒng)一的事件監(jiān)聽(tīng)器上插入或刪除一些對(duì)象
當(dāng)事件發(fā)生時(shí),首先被這個(gè)統(tǒng)一的事件監(jiān)聽(tīng)器處理,然后在映射里找到真正的事件處理函數(shù)并調(diào)用。這樣做簡(jiǎn)化了事件處理和回收機(jī)制,效率也有很大提升
關(guān)于React合成事件與原生事件執(zhí)行順序,可以看看下面一個(gè)例子:
- import React from 'react';
- class App extends React.Component{
- constructor(props) {
- super(props);
- this.parentRef = React.createRef();
- this.childRef = React.createRef();
- }
- componentDidMount() {
- console.log("React componentDidMount!");
- this.parentRef.current?.addEventListener("click", () => {
- console.log("原生事件:父元素 DOM 事件監(jiān)聽(tīng)!");
- });
- this.childRef.current?.addEventListener("click", () => {
- console.log("原生事件:子元素 DOM 事件監(jiān)聽(tīng)!");
- });
- document.addEventListener("click", (e) => {
- console.log("原生事件:document DOM 事件監(jiān)聽(tīng)!");
- });
- }
- parentClickFun = () => {
- console.log("React 事件:父元素事件監(jiān)聽(tīng)!");
- };
- childClickFun = () => {
- console.log("React 事件:子元素事件監(jiān)聽(tīng)!");
- };
- render() {
- return (
- 分析事件執(zhí)行順序
- );
- }
- }
- export default App;
輸出順序?yàn)椋?/p>
- 原生事件:子元素 DOM 事件監(jiān)聽(tīng)!
- 原生事件:父元素 DOM 事件監(jiān)聽(tīng)!
- React 事件:子元素事件監(jiān)聽(tīng)!
- React 事件:父元素事件監(jiān)聽(tīng)!
- 原生事件:document DOM 事件監(jiān)聽(tīng)!
可以得出以下結(jié)論:
對(duì)應(yīng)過(guò)程如圖所示:
所以想要阻止不同時(shí)間段的冒泡行為,對(duì)應(yīng)使用不同的方法,對(duì)應(yīng)如下:
- document.body.addEventListener('click', e => {
- if (e.target && e.target.matches('div.code')) {
- return;
- }
- this.setState({ active: false, }); });
- }
React事件機(jī)制總結(jié)如下:
參考文獻(xiàn)

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流