????????react有兩種寫法,一種是類組件,也叫有狀態(tài)組件;一種是函數(shù)式組件,也叫無狀態(tài)組件,而后引入了react hooks,函數(shù)式組件也能修改狀態(tài)。在這兩種組件中的事件綁定的原理一樣,寫法不一樣。這篇文章主要就是記錄這兩種組件中的事件綁定寫法。
?
一、前提說明
????????重點是記錄兩種組件中事件綁定使用的區(qū)別,避免下次使用的時候還犯迷糊,在下面的寫法中,可能出現(xiàn)同一類組件中多種寫法,只要自己選擇自己喜歡的那種寫就可以了,沒必要每種都要會,能看的懂就可以。想直接拿來用的,可以直接跳過原理,看使用案例,對原理感興趣的可以回頭來看看事件原理。在react中,事件的寫法都是on+事件類型(第一個字母大寫),如點擊事件(onClick),鼠標事件(onMouseOver ,onMouseOut)
二、事件綁定的原理
????????react中的事件都是合成事件,react并不是將click事件綁定到了div的真實DOM上,而是在document處監(jiān)聽了所有的事件,當事件發(fā)生并且冒泡到document處的時候,React將事件內(nèi)容封裝并交由真正的處理函數(shù)運行。這樣的方式不僅僅減少了內(nèi)存的消耗,還能在組件掛在銷毀時統(tǒng)一訂閱和移除事件。
????????另外冒泡到document上的事件也不是原生的瀏覽器事件,而是由react自己實現(xiàn)的合成事件(SyntheticEvent)。因此我們?nèi)绻幌胍鞘录芭莸脑捳{(diào)用event.stopProppagation()方法是無效的。而應該調(diào)用event.preventDefault()。
(一)事件注冊
????????組件更新或者裝載時,在給dom增加合成事件時,需要將增加的target傳入到document進行判斷,給document注冊原生事件回調(diào)為dispatchEvent(統(tǒng)一的事件分發(fā)機制)。
(二)事件存儲
????????EventPluginHub負責管理React合成事件的callback,它將callback存儲到listennerBank中,另外還存儲了負責合成事件的Plugin,Event存儲到listennerbank中,每一個元素在listennerBank中會有唯一的key。
(三)事件觸發(fā)執(zhí)行
????????點擊時冒泡到docunment中,觸發(fā)注冊原生事件的回調(diào)dispatchEvent,獲取到觸發(fā)這個事件的最深層元素,事件執(zhí)行利用react的批處理機制。
(四)合成事件
????????循環(huán)所有類型的eventPlugin,對應每個事件類型,生成不同的事件池,如果是空,則生成新的,有則用之前的,根據(jù)唯一key獲取到指定的回調(diào)函數(shù),再返回帶有參數(shù)的回調(diào)函數(shù)。
(五)總流程
?-- >? 組件裝載/更新
?-- >? 新增/刪除事件
?-- >? eventplugin添加到ListennerBank中監(jiān)聽事件
?-- >? 觸發(fā)事件
?-- >? 生成合成事件
?-- >? 通過唯一key獲取到指定函數(shù)
?-->? ?執(zhí)行指定回調(diào)函數(shù)
?-- >? 執(zhí)行完畢后釋放
三、事件使用案例
(一)類組件的事件綁定
import React, { Component } from 'react'
export default class App1 extends Component {
test2Fn() {
console.log('test2');
}
test3Fn = () => {
console.log('test3');
}
test4Fn = () => {
console.log('test4');
}
render() {
return (
<div>
{/* 直接寫箭頭函數(shù),因為普通函數(shù)有this指向問題 */}
<button onClick={() => { console.log('test1'); }}>第一種</button>
{/* this.test2Fn()會被直接調(diào)用 和 this.test2Fn不一樣*/}
<button onClick={this.test2Fn}>第二種</button>
<button onClick={this.test3Fn}>第三種</button>
<button onClick={() => {
this.test4Fn()
}}>第四種</button>
</div>
)
}
}
個人比較喜歡第三種寫法
第一種寫法有弊端,邏輯長的時候不方便觀看,也不建寫在dom里面
第二種有this指向問題,如定義一個a=100,在方法二中通過this.a獲取會報錯,這是因為this沒有指向App1實例中
?通過this.test2Fn.bind(this)可以解決,這樣可以使兩個this指向一致
import React, { Component } from 'react'
export default class App1 extends Component {
a=100 //添加一個全局變量
test2Fn() {
console.log('test2',this.a);
}
test3Fn = () => {
console.log('test3',this.a);
}
test4Fn = () => {
console.log('test4',this.a);
}
render() {
return (
<div>
{/* 直接寫箭頭函數(shù),因為普通函數(shù)有this指向問題 */}
<button onClick={() => { console.log('test1',this.a); }}>第一種</button>
{/* this.test2Fn()會被直接調(diào)用 和 this.test2Fn不一樣*/}
<button onClick={this.test2Fn.bind(this)}>第二種</button>
<button onClick={this.test3Fn}>第三種</button>
<button onClick={() => {
this.test4Fn()
}}>第四種</button>
</div>
)
}
}
this指向修改
call:? ? 修改this指向,并使函數(shù)自動執(zhí)行(不用函數(shù)()調(diào)用)
apply: 修改this指向,并使函數(shù)自動執(zhí)行(不用函數(shù)()調(diào)用)
bind:? ?修改this指向,需要手動執(zhí)行(用()調(diào)用)文章來源:http://www.zghlxwxcb.cn/news/detail-426196.html
(二)函數(shù)式組件的事件綁定
function App2(){
const test=()=>{
console.log("add");
}
return(
<div >
<button onClick={test}>add</button>
</div>
)
}
export default App2
文章來源地址http://www.zghlxwxcb.cn/news/detail-426196.html
到了這里,關于react——事件綁定的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!