React事件的問題

React?把事件委托到 document 對象上。
當真實 DOM 元素觸發(fā)事件,先處理原生事件,然后會冒泡到 document 對象后,再處理 React 事件。
React事件綁定的時刻是在 reconciliation 階段,會在原生事件的綁定前執(zhí)行
在 React17 以前 React 的合成事件和原生事件存在執(zhí)行順序問題,比如下面的例子,包含了兩個父子關系的 DOM 元素,并且分別給他們綁定 React 事件和原生事件。
import * as React from 'react';import * as ReactDOM from 'react-dom';class App extends React.Component {parentRef=React.createRef();childRef=React.createRef();componentDidMount() {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("子元素原生冒泡");});document.addEventListener('click',()=>{console.log("document捕獲");},true);document.addEventListener('click',()=>{console.log("document冒泡");});}parentBubble = () => {console.log("父元素React事件冒泡");};childBubble = () => {console.log("子元素React事件冒泡");};parentCapture = () => {console.log("父元素React事件捕獲");};childCapture = () => {console.log("子元素React事件捕獲");};render() {return (<div ref={this.parentRef} onClick={this.parentBubble} onClickCapture={this.parentCapture}><p ref={this.childRef} onClick={this.childBubble} onClickCapture={this.childCapture}>事件執(zhí)行順序p>div>);}}ReactDOM.render(<App />, document.getElementById('root'));/**document捕獲父元素原生捕獲子元素原生捕獲子元素原生冒泡父元素原生冒泡父元素React事件捕獲子元素React事件捕獲子元素React事件冒泡父元素React事件冒泡document冒泡*/
通過代碼的執(zhí)行順序我們發(fā)現(xiàn),先執(zhí)行了原生事件的捕獲和冒泡,再執(zhí)行 React 事件的捕獲冒泡。其實比較合理的順序是 React 事件和原生事件都捕獲再原生事件冒泡和 React 事件冒泡。
import * as React from 'react';import * as ReactDOM from 'react-dom';class App extends React.Component {parentRef=React.createRef();childRef=React.createRef();componentDidMount() {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("子元素原生冒泡");});document.addEventListener('click',()=>{console.log("document原生捕獲");},true);document.addEventListener('click',()=>{console.log("document原生冒泡");});}parentBubble = () => {console.log("父元素React事件冒泡");};childBubble = () => {console.log("子元素React事件冒泡");};parentCapture = () => {console.log("父元素React事件捕獲");};childCapture = () => {console.log("子元素React事件捕獲");};render() {return (<div ref={this.parentRef} onClick={this.parentBubble} onClickCapture={this.parentCapture}><p ref={this.childRef} onClick={this.childBubble} onClickCapture={this.childCapture}>事件執(zhí)行順序p>div>);}}ReactDOM.render(<App />, document.getElementById('root'));/**document原生捕獲父元素React事件捕獲子元素React事件捕獲父元素原生捕獲子元素原生捕獲子元素原生冒泡父元素原生冒泡子元素React事件冒泡父元素React事件冒泡document原生冒泡*/
react17 以后合成事件執(zhí)行順序問題已經修復了,React 事件和原生事件都捕獲再原生事件冒泡和 React 事件冒泡。
評論
圖片
表情
