深入了解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 ( <divref={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 ( <divref={this.childRef}onClick={this.handleChildBubble}onClickCapture={this.handleChileCapture} >事件處理測試 </div> ); return ( <divref={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 ( <divref={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 ( <divref={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 ( <divref={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合成事件的資料請關注其它相關文章!