日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
面試官:說說對React事件機(jī)制的理解?

[[408242]]

本文轉(zhuǎn)載自微信公眾號「JS每日一題」,作者灰灰。轉(zhuǎn)載本文請聯(lián)系JS每日一題公眾號。

一、是什么

React基于瀏覽器的事件機(jī)制自身實(shí)現(xiàn)了一套事件機(jī)制,包括事件注冊、事件的合成、事件冒泡、事件派發(fā)等

在React中這套事件機(jī)制被稱之為合成事件

合成事件(SyntheticEvent)

合成事件是 React模擬原生 DOM事件所有能力的一個事件對象,即瀏覽器原生事件的跨瀏覽器包裝器

根據(jù) W3C規(guī)范來定義合成事件,兼容所有瀏覽器,擁有與瀏覽器原生事件相同的接口,例如:

 
 
 
 
  1. const button = 按鈕 

如果想要獲得原生DOM事件,可以通過e.nativeEvent屬性獲取

 
 
 
 
  1. const handleClick = (e) => console.log(e.nativeEvent);; 
  2. const button = 按鈕 

從上面可以看到React事件和原生事件也非常的相似,但也有一定的區(qū)別:

  • 事件名稱命名方式不同
 
 
 
 
  1. // 原生事件綁定方式 
  2. 按鈕命名 
  3.        
  4. // React 合成事件綁定方式 
  5. const button = 按鈕命名 
  • 事件處理函數(shù)書寫不同
 
 
 
 
  1. // 原生事件 事件處理函數(shù)寫法 
  2. 按鈕命名 
  3.        
  4. // React 合成事件 事件處理函數(shù)寫法 
  5. const button = 按鈕命名 

雖然onclick看似綁定到DOM元素上,但實(shí)際并不會把事件代理函數(shù)直接綁定到真實(shí)的節(jié)點(diǎn)上,而是把所有的事件綁定到結(jié)構(gòu)的最外層,使用一個統(tǒng)一的事件去監(jiān)聽

這個事件監(jiān)聽器上維持了一個映射來保存所有組件內(nèi)部的事件監(jiān)聽和處理函數(shù)。當(dāng)組件掛載或卸載時,只是在這個統(tǒng)一的事件監(jiān)聽器上插入或刪除一些對象

當(dāng)事件發(fā)生時,首先被這個統(tǒng)一的事件監(jiān)聽器處理,然后在映射里找到真正的事件處理函數(shù)并調(diào)用。這樣做簡化了事件處理和回收機(jī)制,效率也有很大提升

二、執(zhí)行順序

關(guān)于React合成事件與原生事件執(zhí)行順序,可以看看下面一個例子:

 
 
 
 
  1. import  React  from 'react'; 
  2. class App extends React.Component{ 
  3.  
  4.   constructor(props) { 
  5.     super(props); 
  6.     this.parentRef = React.createRef(); 
  7.     this.childRef = React.createRef(); 
  8.   } 
  9.   componentDidMount() { 
  10.     console.log("React componentDidMount!"); 
  11.     this.parentRef.current?.addEventListener("click", () => { 
  12.       console.log("原生事件:父元素 DOM 事件監(jiān)聽!"); 
  13.     }); 
  14.     this.childRef.current?.addEventListener("click", () => { 
  15.       console.log("原生事件:子元素 DOM 事件監(jiān)聽!"); 
  16.     }); 
  17.     document.addEventListener("click", (e) => { 
  18.       console.log("原生事件:document DOM 事件監(jiān)聽!"); 
  19.     }); 
  20.   } 
  21.   parentClickFun = () => { 
  22.     console.log("React 事件:父元素事件監(jiān)聽!"); 
  23.   }; 
  24.   childClickFun = () => { 
  25.     console.log("React 事件:子元素事件監(jiān)聽!"); 
  26.   }; 
  27.   render() { 
  28.     return ( 
  29.        
  30.          
  31.           分析事件執(zhí)行順序 
  32.         
 
  •       
  •  
  •     ); 
  •   } 
  • export default App; 
  • 輸出順序?yàn)椋?/p>

     
     
     
     
    1. 原生事件:子元素 DOM 事件監(jiān)聽!  
    2. 原生事件:父元素 DOM 事件監(jiān)聽!  
    3. React 事件:子元素事件監(jiān)聽!  
    4. React 事件:父元素事件監(jiān)聽!  
    5. 原生事件:document DOM 事件監(jiān)聽!  

    可以得出以下結(jié)論:

    • React 所有事件都掛載在 document 對象上
    • 當(dāng)真實(shí) DOM 元素觸發(fā)事件,會冒泡到 document 對象后,再處理 React 事件
    • 所以會先執(zhí)行原生事件,然后處理 React 事件
    • 最后真正執(zhí)行 document 上掛載的事件

    對應(yīng)過程如圖所示:

    所以想要阻止不同時間段的冒泡行為,對應(yīng)使用不同的方法,對應(yīng)如下:

    • 阻止合成事件間的冒泡,用e.stopPropagation()
    • 阻止合成事件與最外層 document 上的事件間的冒泡,用e.nativeEvent.stopImmediatePropagation()
    • 阻止合成事件與最外層document上的原生事件上的冒泡,通過判斷e.target來避免
     
     
     
     
    1. document.body.addEventListener('click', e => {    
    2.     if (e.target && e.target.matches('div.code')) {   
    3.         return;     
    4.     }     
    5.     this.setState({   active: false,    });   });  

    三、總結(jié)

    React事件機(jī)制總結(jié)如下:

    • React 上注冊的事件最終會綁定在document這個 DOM 上,而不是 React 組件對應(yīng)的 DOM(減少內(nèi)存開銷就是因?yàn)樗械氖录冀壎ㄔ?document 上,其他節(jié)點(diǎn)沒有綁定事件)
    • React 自身實(shí)現(xiàn)了一套事件冒泡機(jī)制,所以這也就是為什么我們 event.stopPropagation()無效的原因。
    • React 通過隊(duì)列的形式,從觸發(fā)的組件向父組件回溯,然后調(diào)用他們 JSX 中定義的 callback
    • React 有一套自己的合成事件 SyntheticEvent

    參考文獻(xiàn)

    • https://zh-hans.reactjs.org/docs/events.html
    • https://segmentfault.com/a/1190000015725214?utm_source=sf-similar-article
    • https://segmentfault.com/a/1190000038251163

    新聞名稱:面試官:說說對React事件機(jī)制的理解?
    文章URL:http://www.dlmjj.cn/article/cohhcep.html