事件
這里的事件,指的是 React 內部封裝 DOM 組件中的事件
,如 onClick
, onFocus
等,而非我們自己通過 props 傳遞的屬性,并在子組件中手動觸發(fā)的事件
實例
import React, { Component } from 'react';
class TodoList extends Component {
render() {
return (
<div>
<input type="text" />
<button onClick={()=>{
alert(1)
}}>add</button>
<button onClick={this.handelClick}>add2</button>
<button onClick={this.handelClick2}>add3</button>
<button onClick={()=>{
this.handelClick3()
}}>add4</button>
</div>
);
}
handelClick () {
console.log(1)
console.log(this)
}
// 箭頭函數
handelClick2 = () => {
console.log(2)
console.log(this)
}
// 箭頭函數
handelClick3 = () => {
console.log(3)
console.log(this)
}
}
export default TodoList;
react事件聲明
- react事件采用
駝峰式
命名 - react事件接收一個
函數聲明
,不是函數調用的形式
//原生
<div onclick="handleClick()"></div>
//react
<div onClick={this.handleClick}></div>
綁定事件
采用on+事件名的方式
來綁定一個事件.
注意,這里和原生的事件是有區(qū)別的:
原生的事件全是小寫onclick , React里的事件是駝峰 onClick
,React的事件并不是原生事件,而是合成事件
。
事件handler的寫法
- 直接在render里寫行內的箭頭函數(不推薦)
- 在組件內使用
箭頭函數
定義一個方法(推薦) - 直接在組件內
定義一個非箭頭函數
的方法,然后在render里直接使用onClick={this.handleClick.bind(this)} (不推薦)
- 直接在組件內
定義一個非箭頭函數
的方法,然后在constructor里bind(this)(推薦)
Event 對象
和普通瀏覽器一樣,事件handler會被自動傳入一個 event
對象,這個對象和普通的瀏覽器 event
對象所包含的方法和屬性都基本一致。不同的是React中的 event
對象并不是瀏覽器提供的,而是它自己內部所構建的
。它同樣具有 event.stopPropagation
、 event.preventDefault
這種常用的方法.
this問題
實例
import React, { Component } from 'react';
class TodoList extends Component {
render() {
return (
<div>
<input type="text" />
{/* :如果邏輯過不多,此寫法推薦 */}
{/* 可以直接訪問this,無需手動綁定 */}
<button onClick={()=>{
console.log(0)
console.log(this)
}}>add</button>
{/* :此寫法不推薦 */}
{/* 不可以直接訪問this,需手動綁定 -- .bind(this)*/}
<button onClick={this.handelClick.bind(this)}>add2</button>
{/* :此寫法推薦 */}
{/* 可以直接訪問this,無需手動綁定,handelClick2是箭頭函數,可以綁定外部this :此寫法推薦 */}
<button onClick={this.handelClick2}>add3</button>
{/* :此寫法比較推薦,傳參數很方便 */}
{/* 可以直接訪問this,無需手動綁定,onClick調用的是箭頭函數,可以綁定外部this */}
<button onClick={(e)=> this.handelClick3(e)}>add4</button>
</div>
);
}
handelClick () {
console.log(1)
console.log(this)
}
// 箭頭函數
handelClick2 = (evt) => {
console.log(2)
console.log(this)
// 打印 Event 對象
console.log(evt)
}
// 箭頭函數
handelClick3 = (evt) => {
console.log(3)
// 打印 Event 對象
console.log(evt)
}
}
export default TodoList;
為什么使用bind
綁定this
class組件的事件綁定this問題
1. class的方法默認不會綁定 this
,如果沒有綁定 this.handleClick的this 并把它傳入了 onClick,當你調用這個函數的時候 this 的值為 undefined。
class A extends React.Component{
constructor(props){
super(props)
}
handleClick(){
//class的方法默認不會綁定 `this`,this的指向根據調用的方式判斷
//沒有綁定調用的話this為undefined
this.setState({a:1})
}
render(){
return (
<div onClick={this.handleClick}></div>
)
}
}
this問題的解決方式有三種
(1)在constructor
里使用bind為方法綁定this
class A extends React.Component{
constructor(props){
super(props)
this.handleClick= this.handleClick.bind(this); // 注意此處
}
handleClick(){
this.setState({a:1})
}
}
(2)在元素上綁定事件時使用箭頭函數
class A extends React.Component{
constructor(props){
super(props)
}
handleClick(){
//class的方法默認不會綁定 `this`,this的指向根據調用的方式判斷
//沒有綁定調用的話this為undefined
this.setState({a:1})
}
render(){
//render里的this指向自身
return (
<div onClick={()=> this.handleClick() }></div>
)
}
}
(3)使用箭頭函數
聲明方法
class A extends React.Component{
constructor(props){
super(props)
}
handleClick=()=>{
//箭頭函數的this由父作用域的this判斷
this.setState({a:1})
}
render(){
//render里的this指向自身
return (
<div onClick={this.handleClick}></div>
)
}
}
react事件傳遞參數
1.要在綁定事件的位置給事件傳參有兩種方式,
(1)通過bind
,使用bind
會隱式傳入事件對象e
,作為函數的最后一個參數。
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
(2)通過箭頭函數
,使用箭頭函數需要主動傳入事件對象
e 。
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
事件說明
React 根據 W3C 規(guī)范定義了合成事件 (SyntheticEvent
),我們就無需擔心跨瀏覽器的兼容性問題
React 出于性能與事件管理方面的考量,在之前的 React 版本中 (v17 之前)
- 會將在 JSX 中注冊的事件收集到 document 上 (即通過
事件委托
,在 document 上注冊事件,等觸發(fā)事件時,則按虛擬 DOM 樹
的結構進行事件觸發(fā)機制去分發(fā)事件); - 幾乎所有的事件處理,均在 document 的事件中處理
- 比如
onFocus
等事件不會冒泡的事件,就不做委托,直接在元素上監(jiān)聽 - 一些
document 上沒有的事件
,也直接在元素上監(jiān)聽 (如:audio、video標簽的事件等)
- 比如
- 在 document 中的事件處理,會根據虛擬 DOM 樹的結構完成事件函數的調用,默認是
冒泡機制
(事件捕獲要通過類似onClickCapture
的方式注冊) - React 的事件參數,并非真實的事件參數,而是 React 合成的一個對象 (
SyntheticEvent
)- 通過調用
e.stopPropagation()
阻止事件冒泡 (僅阻止 React 事件) - 通過
e.nativeEvent
可以得到真實的 DOM 事件對象 (不過很少會用到) - 為了提高效率,React 使用事件
對象池
來處理事件對象 (即事件對象會重用)
- 通過調用
- 在 React 17 之后,
事件委托的節(jié)點就轉移到了渲染的根節(jié)點上
,而且也幫我們解決了此類關于事件冒泡的問題 (本文測試用例則說明,對于使用 ReactDOM.createPortal 創(chuàng)建的組件,表現上略有差異)
注意點
- 若給真實 DOM 注冊事件,并阻止冒泡,則很有可能導致 React (JSX) 中注冊的相關事件無法觸發(fā)
- 若給真實 DOM 注冊事件,它會先于 React 事件執(zhí)行 (即通過
onClick
和dom.addEventListener
綁定的事件,真實 DOM 事件會先執(zhí)行;因為這個元素被點擊時,真實 DOM 事件會很快找到,而 React 綁定的事件則需要去找到事件委托的元素,再去調用當前點擊元素綁定的事件函數) - 過 React 事件阻止事件冒泡,無法阻止真實 DOM 事件的冒泡
- 可以使用
e.nativeEvent.stopImmediatePropagation()
去阻止 document 上剩余的事件處理程序的運行 (當我們在使用某些第三方庫,在這個庫有可能使用了一些事件處理,也對 document 綁定過點擊事件,如:document.addEventListener("click", handler)
) - 在事件處理程序中,不要異步使用事件對象
e
;如果一定有異步使用的需求,則需要調用e.persist()
函數持久化保存此事件對象 (代價自然是損耗效率的)
React 事件總結
綁定事件處理函數
1.1 鼠標類
- onContextMenu
- onClick
- onDoubleClick
- onMouseDown
- onMouseUp
- onMouseEnter
- onMouseLeave
- onMouseMove
- onMouseOut
- onMouseOver
1.2 拖拽事件:
- onDrop
- onDrag
- onDragStart
- onDragEnd
- onDragEnter
- onDragLeave
- onDragOver
- onDragExit
1.3 觸摸
觸摸只會在移動設備上產生
- onTouchStart
- onTouchEnd
- onTouchMove
- onTouchCancel
1.4 鍵盤
onKeyPress是onKeyDown和onKeyUp的組合
- onKeyPress
- onKeyDown
- onKeyUp
剪切類
對應的是我們常常使用的復制
、剪切
和粘貼
- onCopy
- onCut
- onPaste
表單類
- onChange
- onInput
- onSubmit
- onChange可以用在輸入框、單選框、下拉列表里,每當內容發(fā)生變化時我們都能獲得通知。
onInput使用在文字輸入。
onSubmit是用在整個表單的輸入提交,常用在禁止表單的默認操作。
1.7 焦點事件
- onFocus
- onBlur
1.8 UI元素類
- onScroll
滾動事件觸發(fā)的時候會觸發(fā)onScroll事件
1.9 滾動
- onWheel
鼠標滾輪觸發(fā)的事件,監(jiān)聽滾動幅度,滾動方位
1.10 組成事件
- onCompositionEnd
- onCompositionStart
- onCompositionUpdate
1.11 圖片類
- onLoad
- onError
1.12 多媒體類
- onAbort
- onCanPlay
- onCanPlayThrough
- onDurationChange
- onEmptied
- onEncrypted
- onEnded
- onError
- onLoadedData
- onLoadedMetadata
- onLoadStart
- onPause
- onPlay
- onPlaying
- onProgress
- onRateChange
- onSeeked
- onSeeking
- onStalled
- onSuspend
- onTimeUpdate
- onVolumeChange
- onWaiting
事件池
虛擬事件對象已經被合并
。這意味著虛擬事件對象將被重新使用,而該事件回調被調用之后所有的屬性將無效。這是出于性能的考慮。因此,您不能以異步的方式訪問事件。
function onClick(event) {
console.log(event); // =>無效的對象
console.log(event.type); // => "click"
var eventType = event.type; // => "click"
setTimeout(function() {
console.log(event.type); // => null
console.log(eventType); // => "click"
}, 0);
this.setState({clickEvent: event}); // 不起作用.this.state.clickEvent 將只包含空值.
this.setState({eventType: event.type}); // 您依然可以導出事件屬性
}
如果您想以一個異步的方式來訪問事件屬性,您應該對事件調用event.persist()
。這將從事件池中取出合成的事件,并允許該事件的引用,使用戶的代碼被保留。
事件對象
事件處理器將會傳入SyntheticEvent的實例
,一個對瀏覽器本地事件的跨瀏覽器封裝。它有和瀏覽器本地事件有相同的屬性和方法,包括stopPropagation()
和preventDefault()
,但是沒有瀏覽器兼容問題。
如果因為一些因素,需要底層的瀏覽器事件對象,只要使用nativeEvent
屬性就可以獲取到它了。
對于 v0.14,在事件處理函數中返回 false 將不會阻止事件冒泡。取而代之的是在合適的應用場景下,手動調用e.stopPropagation()
或者e.preventDefault()
。
handleChange:function(e){
console.log(e.target.value);
}
其中target是 事件對象e 是事件對象的屬性
通用屬性
(以下內容括號內為類型)
- bubbles (boolean) 表示事件是否冒泡
- cancelable(boolean) 表示事件是否可以取消
- currentTarget(DOMEventTarget) 與Target類似,由于事件可以冒泡,所以兩者表示的內容是不同的
- defaultPrevented(boolean) 表示事件是否禁止了默認行為
- eventPhase(number) 表示事件所處的階段
- isTrusted(boolean) 表示事件是否可信。所謂的可信事件表示的是用戶操作的事件,不可信事件就是通過JS代碼來觸發(fā)的事件。
- nativeEvent(DOMEvent)
- preventDefault() (void) 對應的defaultPrevented,表示的是禁止默認行為
- stopPropagaTion() (void) 對應的是bubbles,表示的是sh
- target(DOMEventTarget)
- timeStamp(number) 時間戳,也就是事件觸發(fā)的事件
- type(string) 事件的類型
不同事件對象的特有屬性
剪切事件
- clipboardData(DOMDataTransfer)表示拿到的數據
鍵盤事件
- ctrlKey(boolean) 表示是否按下ctrl鍵
- altKey(boolean) 表示是否按下alt鍵
- shiftKey(boolean) 表示是否按下shift
- metaKey(boolean) 表示的是win系統(tǒng)下的win鍵,mac系統(tǒng)下對應的command鍵
- getModifierState(key) (function) 表示是否按下輔助按鍵(輔助按鍵就是雷士ctrl、shift等輔助按鍵)可以傳入按鍵編碼來判斷是否按下
- charCode(Number) 表示的是按鍵的字符編碼,可以通過編碼來判斷按下的是什么鍵
- key(string) 字符串,按下的鍵
- keyCode(Number) 表示那些不是字符編碼的按鍵
- which(Number) 表示經過通用化得charCode和keyCode
- locale(String) 表示本地化得一些字符串
- location(number) 表示位置
- repeat(boolean) 表示按鍵是否重復
焦點事件
- relatedTarget(DOMEventTarget) 相關焦點對象
鼠標事件
- ctrlKey(boolean)
- altKey(boolean)
- shiftKey(boolean)
- metaKey(boolean)
- getModifierState(key) (function)
- button(Number)
- buttons(Number)
- clientX(Number) 原點為瀏覽器左上角
- clinetY(Number) 原點為瀏覽器左上角
- pageX(Number) 原點為HTML頁面的左上角
- pageY(Number) 原點為HTML頁面的左上角
- screenX(Number) 原點為顯示器的左上角
- screenY(Number) 原點為顯示器的左上角
- relatedTarget(DOMEventTarget)
觸摸事件
為了使觸摸事件生效,在渲染所有組件之前調用 React.initializeTouchEvents(true)。
- ctrlKey(boolean)
- altKey(boolean)
- shiftKey(boolean)
- metaKey(boolean)
- getModifierState(key)
- changedTouches(DOMTouchList) 判斷手勢操作
- targetTouches(DOMTouchList) 判斷手勢操作
- touches(DOMTouchList) 判斷手勢操作
UI元素事件
- detail(Number) 滾動的距離
- view(DOMAbstractView) 界面,視窗
鼠標滾動
- deltaMode(Number) 可以理解為移動的單位
- deltaX(Number) X軸移動的相對距離固定值
- deltaY(Number) Y軸移動的相對距離固定值
- deltaZ(Number) Z軸移動的相對距離固定值
實例
滾動事件對象
var HelloDada = React.creatClass({
getInitialState:function(){
return {
backgroundColor:'#FFFFFF'
}
},
handleWheel:function(e){
var newColor = (parseInt(this.state.backgroundColor.substr(1),16)+e.deltaY*997).tiString(16);
this.setState({
backgroundColor:newColor
})
},
render:function(){
return <div onWheel={this.handleWheel} style={this.state}> // 注意這里 onWheel
<p>Dada Shuaige</p>
</div>
}
});
ReactDOM.render(<HelloDada />,document.body)
鍵盤事件對象
var Dada =React.creatClass{
getInitialState:function(){
return{
password:''
}
},
handleKeyPress:function(e){
this.setState({
paddword:this.state.password+e.which
});
},
handleChange:function(e){
e.target.value='';
},
render:function(){
return <div>
<input onKeyPress={this.handleKeyPress} onChange={this.handleChange} /> // 注意這里 onKeyPress
<p style={{
'display':this.state.password.indexOf('495051') >=0?'block':'none'
}}>Dada handsomeboy</p>
</div>
}
};
ReactDOM.render(<Dada />,document.body)
事件與狀態(tài)關聯(lián)
狀態(tài)不僅僅實現了組件內部結果的清晰對應,還實現了組件與用戶之間的交互,使用戶與組件的行為緊緊結合起來
handleChange:function(e){
this.setState({Dada:e.target.value});
}
this.setState設置狀態(tài)
實例
var Dada =React.creatClass({
getInitialState:function(){
return{
x:0,
y:0
}
},
handleMouseMove:function(e){
this.setState({
x:e.clientX,
y:e.clientY
});
},
render:function(){
return <div onMouseMove={this.handleMouseMove} style={{ // 注意這里 onMouseMove
width:'200px',
height:'200px',
backgroundColor:'#999'
}}>
{this.state.x+'.'+this.state.y}
</div>
}
});
ReactDOM.render(<Dada />,document.body)
React綁定事件和原生綁定事件的區(qū)別
react事件和原生事件的區(qū)別是:
- react中的事件是
綁定到document上面
, React并不會真正的綁定事件到每一個具體《》的元素上,而是采用事件代理
的模式: - 而原生的事件是
綁定到dom上面
。
相對綁定的地方來說,dom上的事件要優(yōu)先于document上的事件執(zhí)行,react的事件對象是合成。文章來源:http://www.zghlxwxcb.cn/news/detail-753412.html
參考鏈接:文章來源地址http://www.zghlxwxcb.cn/news/detail-753412.html
- https://blog.csdn.net/qq_40340943/article/details/107309779
- https://www.bbsmax.com/A/Gkz1PBOgdR/
到了這里,關于react之事件處理的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!