摘要:組件事件響應在構建虛擬的同時,還構建了自己的事件系統且所有事件對象和規范保持一致。的事件系統和瀏覽器事件系統相比,主要增加了兩個特性事件代理和事件自動綁定。
React組件事件響應
React在構建虛擬DOM的同時,還構建了自己的事件系統;且所有事件對象和W3C規范
保持一致。
React的事件系統和瀏覽器事件系統相比,主要增加了兩個特性:事件代理、和事件自動綁定。
1、事件代理區別于瀏覽器事件處理方式,React并未將事件處理函數與對應的DOM節點直接關聯,而是在頂層使用
了一個全局事件監聽器監聽所有的事件;
React會在內部維護一個映射表記錄事件與組件事件處理函數的對應關系;
當某個事件觸發時,React根據這個內部映射表將事件分派給指定的事件處理函數;
當映射表中沒有事件處理函數時,React不做任何操作;
當一個組件安裝或者卸載時,相應的事件處理函數會自動被添加到事件監聽器的內部映射表中或從表中刪除。
2、事件自動綁定在JavaScript中創建回調函數時,一般要將方法綁定到特定的實例,以保證this的正確性;
2.在React中,每個事件處理回調函數都會自動綁定到組件實例(使用ES6語法創建的例外);
注意:事件的回調函數被綁定在React組件上,而不是原始的元素上,即事件回調函數中的
this所指的是組件實例而不是DOM元素;
了解更多React中的thisReact組件中的this。
3、合成事件與瀏覽器事件處理稍微有不同的是,React中的事件處理程序所接收的事件參數是被稱為“合成事件(SyntheticEvent)”的實例。
合成事件是對瀏覽器原生事件跨瀏覽器的封裝,并與瀏覽器原生事件有著同樣的接口,如stopPropagation(),preventDefault()等,并且
這些接口是跨瀏覽器兼容的。
如果需要使用瀏覽器原生事件,可以通過合成事件的nativeEvent屬性獲取
React合成事件原理
使用JSX,在React中綁定事件:
React并不是將click事件綁在該div的真實DOM上,而是在document處監聽所有支持的事件,當事件發生并冒泡至document處時,React將事件內容封裝并交由真正的處理函數運行
每個合成事件有以下通用屬性:
- boolean bubbles - boolean cancelable - DOMEventTarget currentTarget - boolean defaultPrevented - number eventPhase - boolean isTrusted - DOMEvent nativeEvent - void preventDefault() - boolean isDefaultPrevented() - void stopPropagation() - boolean isPropagationStopped() - DOMEventTarget target - number timeStamp - string type
注意:現版本React在事件處理程序通過中返回false停止傳播,已不可用;
取而代之的是需要手動調用e.stopPropagation()或e.preventDefalult().
onCopy onCut onPaste
2、鍵盤事件onKeyDown onKeyPress onKeyUp
3、焦點事件onFocus onBlur
這些焦點事件工作在 React DOM 中所有的元素上 ,不僅是表單元素。
4、表單事件onChange onInput onSubmit
onChange事件經過React改良,內容改變時即可實時觸發;而原生的需內容改變且失去焦點后觸發才觸發。
5、鼠標事件onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp
onMouseEnter 和 onMouseLeave 事件從離開的元素傳播到正在進入的元素,而不是普通的冒泡,并且沒有捕獲階段;只有在鼠標指針穿過被選元素時,才會觸發。
onMouseOut onMouseOver事件:不論鼠標指針穿過被選元素或其子元素,都會觸發。
6、選擇事件onSelect
7、觸摸事件onTouchCancel onTouchEnd onTouchMove onTouchStart
8、UI事件onScroll
9、滾輪事件onWheel
10、圖像事件onLoad onError
11、動畫事件onAnimationStart onAnimationEnd onAnimationIteration
12、其他事件onToggle
在React中使用原生事件由于原生事件需要綁定在真實DOM上,所以一般是在 componentDidMount階段/ref的函數執行階段進行綁定操作,在componentWillUnmount 階段進行解綁操作以避免內存泄漏。
import React,{Component} from "react"; import ReactDOM from "react-dom" class ReactEvent extends Component { componentDidMount() { //獲取當前真實DOM元素 const thisDOM = ReactDOM.findDOMNode(this); thisDOM.addEventListener("click",this.onDOMClick,false); } componentWillUnmount() { //卸載時解綁事件,防止內存泄漏 const thisDOM = ReactDOM.findDOMNode(this); thisDOM.removeEventListener("click",this.removeDOMClick); } onDOMClick(e){ console.log(e) } render(){ return(合成事件和原生事件混合使用單擊原始事件觸發) } } export default ReactEvent
響應順序
import React,{Component} from "react"; import ReactDOM from "react-dom" class ReactEvent extends Component { constructor(props){ super(props) this.state = { value: "" } this.onReactClick = this.onReactClick.bind(this) } componentDidMount() { //獲取當前真實DOM元素 const thisDOM = ReactDOM.findDOMNode(this); thisDOM.addEventListener("click",this.onDOMClick,false); } componentWillUnmount() { //卸載時解綁事件,防止內存泄漏 const thisDOM = ReactDOM.findDOMNode(this); thisDOM.removeEventListener("click",this.removeDOMClick); } onDOMClick(e){ console.log("原生事件綁定事件觸發") } onReactClick(e){ console.log("React合成事件綁定事件觸發") } render(){ return(單擊事件觸發) } } export default ReactEvent
首先DOM事件監聽器被執行,然后事件繼續冒泡至document,合成事件監聽器再被執行。
即,最終控制臺輸出為:
原生事件綁定事件觸發
合成事件綁定事件觸發
阻止冒泡
如果在onDOMClick中調用e.stopPropagtion()
onDOMClick(e){ e.stopPropagation() console.log("原生事件綁定事件觸發") }
由于DOM事件被阻止冒泡了,無法到達document,所以合成事件自然不會被觸發,控制臺輸出就變成了:
原生事件綁定事件觸發
再測試個復雜的例子
import React,{Component} from "react"; import ReactDOM from "react-dom" class ReactEvent extends Component { constructor(props){ super(props) this.state = { value: "" } this.onReactClick = this.onReactClick.bind(this) this.onReactChildClick = this.onReactChildClick.bind(this) } componentDidMount() { //獲取當前真實DOM元素 const thisDOM = ReactDOM.findDOMNode(this); thisDOM.addEventListener("click",this.onDOMClick,false); //獲取子元素并綁定事件 const thisDOMChild = thisDOM.querySelector(".child"); thisDOMChild.addEventListener("click",this.onDOMChildClick,false); } onDOMClick(e){ console.log("父組件原生事件綁定事件觸發") } onReactClick(e){ console.log("父組件React合成事件綁定事件觸發") } onDOMChildClick(e){ e.stopPropagation() console.log("子元素原生事件綁定事件觸發") } onReactChildClick(e){ console.log("子元素React合成事件綁定事件觸發") } render(){ return(父元素單擊事件觸發) } } export default ReactEvent
通過設置原生事件綁定為冒泡階段調用,且每次測試單擊子元素按鈕:
在子元素原生事件程序中阻止事件傳播,則打印出:
子元素原生事件綁定事件觸發;
在父元素元素事件程序中阻止事件傳播,則打印出:
子元素原生事件綁定事件觸發
父組件原生事件綁定事件觸發
在子元素React合成事件onClick中阻止事件傳播,則打印出:
子元素原生事件綁定事件觸發
父組件原生事件綁定事件觸發
子元素React合成事件綁定事件觸發
在父元素React合成事件onClick中阻止事件傳播,則打印出:
子元素原生事件綁定事件觸發
父組件原生事件綁定事件觸發
子元素React合成事件綁定事件觸發
父組件React合成事件綁定事件觸發
可以看到若不阻止事件傳播每次(單擊子元素)事件觸發流程是:
Document->子元素(原生事件觸發)->父元素(原生事件)->回到Document->React子元素合成事件監聽器觸發 ->React父元素合成事件監聽器觸發
其實,React合成事件封裝的stopPropagtion函數在調用時給自己加了個isPropagationStopped的標記位來確定后續監聽器是否執行。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93282.html
摘要:導航組件使用詳解注意了,如果有小伙伴們發現運行作者提供的示例項目報如下的錯誤,可能是大家使用了命令導致的,解決這個錯誤的辦法就是將刪除,然后重新使用命令來安裝,最后使用來起服務,應該就不報錯了。 react-navigation導航組件使用詳解 注意了,如果有小伙伴們發現運行作者提供的react-navigation示例項目報如下的錯誤,可能是大家使用了 yarn install 命...
本文主要講述ref 的應用僅為父組件調用子組件場景下的應用方式1 Class組件 1. 自定義事件 Parent.js importReact,{Component}from'react'; importChildfrom'./Child'; classParentextendsComponent{ componentDidMount(){ ...
閱讀 1607·2021-11-23 09:51
閱讀 1177·2019-08-30 13:57
閱讀 2256·2019-08-29 13:12
閱讀 2011·2019-08-26 13:57
閱讀 1192·2019-08-26 11:32
閱讀 978·2019-08-23 15:08
閱讀 699·2019-08-23 14:42
閱讀 3079·2019-08-23 11:41