[React 基礎系列] 事件處理
- 事件處理基礎
- 常用的事件處理方法
- 滑鼠事件 - onClick
- 聚焦事件
- 表單事件 - onChange
- 總結
在 狀態 & 狀態更新 & 生命周期方法 中曾經簡略的提到了在 onChange 這個事件處理機制中更新狀態,本篇更加相近地講一下在我過去開發中碰到使用比較多的事件,以及一些常用的處理事件的方法和經驗,
之前復習過的內容有:
- 什么是 JSX,以及如何使用 JSX
- 元素 vs 組件
- 狀態 & 狀態更新 & 生命周期方法
這部分的學習資源在 [React 基礎系列] 事件處理-案例
事件處理基礎
React 的事件處理核心邏輯與傳統的 JavaScript 還是一樣的,都是通過回呼函式去執行,假設 JavaScript 的 點擊事件處理函式(onclickHandler) 都已經實作好了:
const onclickHandler = () => {
console.log('button clicked');
};
在 HTML 中的呼叫是這么實作的:
<button onclick="onclickHandler()">btn</button>
React 中的實作和在 HTML 中的實作就有些不太一樣了,以類組件為例:
class Input extends Component {
// 類組件宣告函式是不需要 const 關鍵字的
onclickHandler = () => {
console.log('button clicked');
};
render() {
// 注意 onClick 的大小寫問題,以及參考是不帶括號的
return <button onClick={this.onclickHandler}>submit</button>;
}
}
這里使用箭頭函式是因為箭頭函式里面不存在 this 的指向問題,注意這里并沒有直接呼叫 this.onclickHandler,React 內部有其他的處理機制去呼叫 this.onclickHandler,所以如果是用傳統的函式式寫法,就會出現 this指向 出錯問題:
class Input extends Component {
onclickHandler() {
console.log('button clicked');
}
}
在呼叫 this 的時候就會引發下列報錯:

所以,如果是用傳統的函式式寫法,就需要在建構式中使用 bind 去系結 this 的指向:
class Input extends Component {
constructor(props) {
super(props);
this.onclickHandler = this.onclickHandler.bind(this);
}
}
this 的指向和 bind 的用法屬于 JavaScript 的通用問題,并不只是針對 React 的類組件而實行的,在處理任何的組件以及較為復雜的 JavaScript 邏輯時,都需要注意 this 的指向問題,
簡單的總結一下,主要的差別有 2 個:
- 參考的函式不包含小括號
() - React 中為了防止關鍵字沖突所以有
onclick與onClick的區別
另外一個需要注意的點就是 this 的指向問題和 bind 的使用,關于什么時候使用箭頭函式去處理事件,什么時候使用 bind 去系結函式,根據官網的這番話:
此語法(在回呼函式中使用箭頭函式,語法為:
{() => this.handleClick()}) 問題在于每次渲染 LoggingButton 時都會創建不同的回呼函式,在大多數情況下,這沒什么問題,但如果該回呼函式作為 prop 傳入子組件時,這些組件可能會進行額外的重新渲染,我們通常建議在構造器中系結或使用 class fields 語法來避免這類性能問題,
就可以理解為說,如果當前的事件處理只需要在本組件內被呼叫,不需要傳給其他的組建去處理,使用箭頭函式是沒有問題的;但是,如果函式需要被作為 props 傳給其他的組件,那么就需要使用 bind 去確認 this 的指向問題,
常用的事件處理方法
React 封裝的時間處理方法還挺多的,完整的 API 可以參考 SyntheticEvent 這里查看所有支持的事件,這里只是就經驗列舉幾個之前開發程序中比較常用的事件,
滑鼠事件 - onClick
onClick 的使用就像上半部分使用的案例一樣,一般來說使用 onClick 的場景主要在:
-
頁面重定向
如有些頁面會有的不同按鈕,上一頁、下一頁、回傳,都在 onClick 中進行事件處理
-
API 呼叫
這種更多的在搜索功能、提交表單使用,
提交表單真的要根據業務實作的方式了,有使用 onClick 實作的,也有使用 onSubmit 實作的,
-
radio/checkbox 選中后更新狀態
-
a 標簽的處理
這時候要特別注意
preventDefault()呼叫的問題,React 中要阻止默認行為——如 a 標簽默認會打開新的頁面或者重定向這種情況,就必須要呼叫e.preventDefault();去阻止默認行為,當然,React 其實也建議,如果不需要頁面的重定向,其實可以不用 a 標簽,而是使用 span 搭配 CSS 進行實作,
聚焦事件
聚焦事件總共有兩個,一個是 onFocus(聚焦時被呼叫),一個是 onBlur(失去焦點時會被呼叫),
其中 onFocus 使用的場景比較少,用的更多的是 onBlur,在表單內容失去聚焦的時候對其進行驗證,如果資料有問題就直接清空,下面是簡單的案例:
class Input extends Component {
blurEvent = () => {
console.log(this.state.input, 'onblur');
// 如果電話號碼不是11位就自動清空
if (this.state.input.length !== 11) {
this.setState({
input: '',
});
}
};
render() {
return (
<div>
<div>
<label>{this.props.label}</label>
<input
type="text"
value={this.state.input}
onChange={(e) => this.updateInputHandler(e)}
onBlur={this.blurEvent}
/>
</div>
<button onClick={this.onclickHandler}>submit</button>
</div>
);
}
}
效果如下:
可以看到,在 onBlur 中的 this.setState 觸發之后,也會觸發 componentDidUpdate,所以當頁面邏輯比較復雜的情況下,一定要注意 componentDidUpdate 的實作,避免進入無限死回圈的狀態,
表單事件 - onChange
上一篇 狀態 & 狀態更新 & 生命周期方法 中已經實作了 onChange 方法,不過使用的是在箭頭函式中呼叫箭頭函式的方法:onChange={(e) => this.updateInputHandler(e)},
這里更新為使用 bind 的方法進行重寫:
class Input extends Component {
constructor(props) {
// 也必須要呼叫 super(props)
super(props);
this.state = { input: '13001301300' };
// 添加 bind 事件
this.updateInputHandler = this.updateInputHandler.bind(this);
}
// 函式的實作方法不需要改變
render() {
return (
<div>
<label>{this.props.label}</label>
<input
type="text"
value={this.state.input}
// 原本的 onChange 呼叫被注釋了
// onChange={(e) => this.updateInputHandler(e)}
onChange={this.updateInputHandler}
onBlur={this.blurEvent}
/>
</div>
);
}
}
這個實作方式還是比較建議去做的,尤其是表單的 input, radio, checkbox 這種組件其實可以被單獨拉出來拆分的情況下,就需要將時間處理函式作為 props 傳到子組件里,頁面上的表單內容多了的情況下,確實需要考慮一下業務的優化問題,
總結
這章學習了一下事件處理方法,著重講了三種不同的事件處理分類:
- HTML 中的事件處理
- React 中不需要傳引數的事件處理
- React 中需要傳引數的事件處理
對于 2 和 3 點,也分別使用了不同的實體事件:onClick, onChange, onBlur 進行學習,
其他的事件基本可以參照這三個較為常用的事件去進行事件,畢竟 React 對于方法的封裝和實作都是基于同一套理念,也必然會在內部進行封裝,故此,函式的實作及呼叫方法也是差不多的,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/292063.html
標籤:其他
