[傳送門](事件處理 – React (reactjs.org))
組件與事件綁定
本章包含以下內(nèi)容:
- React 中的組件
- 為組件綁定事件
- this 的指向
- 向事件處理函數(shù)傳參
React 中的組件
在 React 中,可以使用類的方式來聲明一個(gè)組件。
class 類名 extends React.Component{
render(){
return (
// 一段 JSX
)
}
}
除了類組件,React 中還支持使用函數(shù)來創(chuàng)建組件,同樣需要返回一段 JSX,來表示這個(gè)組件的 UI 是什么樣的。
function 組件名(){
return (
// 一段 JSX
);
}
早期的函數(shù)組件被稱之為無狀態(tài)組件,一般僅僅用來做純 UI 的展示,里面不會(huì)有復(fù)雜的邏輯。
但是從 React 16.8 推出 Hooks 后,現(xiàn)在更多的是使用函數(shù)組件了。
這不僅僅是語法的改變,同時(shí)也代表著整個(gè) React 編程思想的一種轉(zhuǎn)變。
為組件綁定事件
在 React 中綁定事件的寫法如下:
<button onClick={activateLasers}>Activate Lasers</button>
在 React 中無法通過 return false 來阻止默認(rèn)行為,所以只有使用 e.preventDefault 的方式來阻止默認(rèn)行為。
function Form() {
function handleSubmit(e) {
e.preventDefault();
console.log('You clicked submit.');
}
return (
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
);
}
如果是類組件,那么事件處理函數(shù)寫作一個(gè)類方法。
class Welcome extends React.Component {
// 事件處理函數(shù)
eventHandler(e){
window.alert('Hello');
e.preventDefault();
}
render() {
return (
<a onClick={this.eventHandler}>this is a test</a>
);
}
}
在 React 的事件處理函數(shù)中所傳入的事件對象,是一個(gè)合成事件對象。
React 也提供了訪問原生事件對象的方式。如下:
eventHandler(e){
e.nativeEvent // 原生事件對象
}
this 的指向
在react的類組件中,通過以下方法調(diào)用函數(shù),this的值將會(huì)指向undefined
import React, { Component } from 'react'
//改變this指向
export default class ClassComp extends Component {
clickHandle(){
console.log(this);//這里打印出來是undefined
}
render() {
return (
<div>
{/* <a onClick={(e)=>{e.preventDefault()}}>百度一下,你就知道了</a> */}
<button onClick={this.clickHandle}>按鈕</button>
</div>
)
}
}
但這并不是react的問題,而是由于 JS 中 this 的特殊性,事件處理函數(shù)中的 this 并不會(huì)指向當(dāng)前的組件,這就需要我們自行對 this 進(jìn)行指向的修正。
這里介紹 3 種解決方式:
- 將事件處理函數(shù)修改為箭頭函數(shù)
- 將事件綁定修改為箭頭函數(shù)
- 使用 bind 方法來強(qiáng)制綁定 this 的指向
針對以上三種解決方法,現(xiàn)分別舉例如下:
方法一:將事件處理函數(shù)修改為箭頭函數(shù)
import React, { Component } from 'react'
//改變this指向
export default class ClassComp extends Component {
clickHandle=()=>{
console.log(this);//現(xiàn)在在瀏覽器中就會(huì)打印出當(dāng)前組件實(shí)例
}
render() {
return (
<div>
{/* <a onClick={(e)=>{e.preventDefault()}}>百度一下,你就知道了</a> */}
<button onClick={this.clickHandle}>按鈕</button>
</div>
)
}
}
方法二:將事件綁定修改為箭頭函數(shù)
import React, { Component } from 'react'
//改變this指向
export default class ClassComp extends Component {
clickHandle(){
console.log(this);//現(xiàn)在在瀏覽器中就會(huì)打印出當(dāng)前組件實(shí)例
}
render() {
return (
<div>
{/* <a onClick={(e)=>{e.preventDefault()}}>百度一下,你就知道了</a> */}
<button onClick={()=>this.clickHandle()}>按鈕</button>
</div>
)
}
}
import React, { Component } from 'react'
//改變this指向
export default class ClassComp extends Component {
clickHandle(){
console.log(this);//現(xiàn)在在瀏覽器中就會(huì)打印出當(dāng)前組件實(shí)例
}
render() {
return (
<div>
{/* <a onClick={(e)=>{e.preventDefault()}}>百度一下,你就知道了</a> */}
<button onClick={()=>this.clickHandle()}>按鈕</button>
</div>
)
}
}
方法三:使用 bind 方法來強(qiáng)制綁定 this 的指向
import React, { Component } from "react";
export default class ClassComp extends Component {
constructor(props) {
super(props);
this.clickHandle = this.clickHandle.bind(this);
}
clickHandle() {
console.log(this);
}
render() {
return (
<div>
{/* <a onClick={(e)=>{e.preventDefault()}}>百度一下,你就知道了</a> */}
<button onClick={this.clickHandle}>按鈕</button>
</div>
);
}
}
向事件處理程序傳參
另外還有一個(gè)非常重要的問題,就是如何向事件處理函數(shù)傳遞參數(shù)。
如果要傳遞參數(shù),可以使用下面的兩種方式來進(jìn)行傳參:
- 通過 bind 方法在綁定 this 指向時(shí)向事件處理函數(shù)進(jìn)行傳參
- 綁定事件時(shí),通過書寫箭頭函數(shù)的形式來傳參
舉例來說:
案例一:綁定事件時(shí),通過書寫箭頭函數(shù)的形式來傳參
import React, { Component } from "react";
export default class ClassComp extends Component {
constructor(props) {
super(props);
this.state = {
list: [
{ id: 1, name: "lisi", age: 18 },
{ id: 2, name: "lisi2", age: 18 },
{ id: 3, name: "lisi3", age: 18 },
],
};
}
deleteRow(id, e) {
this.setState((prevState) => ({
list: prevState.list.filter((item) => item.id !== id),
}));
}
render() {
return (
<ul>
{this.state.list.map((item) => (
<li key={item.id}>
{item.name}
<button
onClick={()=>this.deleteRow(item.id)}
>
刪除
</button>
</li>
))}
</ul>
);
}
}
案例二:通過 bind 方法在綁定 this 指向時(shí)向事件處理函數(shù)進(jìn)行傳參
import React, { Component } from "react";
export default class ClassComp extends Component {
constructor(props) {
super(props);
this.state = {
list: [
{ id: 1, name: "lisi", age: 18 },
{ id: 2, name: "lisi2", age: 18 },
{ id: 3, name: "lisi3", age: 18 },
],
};
}
deleteRow(id) {
// 使用prevState參數(shù)基于前一個(gè)狀態(tài)來更新list,過濾掉要?jiǎng)h除的項(xiàng)
this.setState((prevState) => ({
list: prevState.list.filter((item) => item.id !== id),
}));
}
render() {
return (
<ul>
{this.state.list.map((item) => (
<li key={item.id}>
{item.name}
{/* 使用bind來綁定函數(shù)并傳參,注意這里要返回一個(gè)新的函數(shù) */}
<button onClick={this.deleteRow.bind(this, item.id)}>刪除</button>
</li>
))}
</ul>
);
}
}
今天的筆記就寫到這里了,每天進(jìn)步一小步,日積月累,水滴石穿