[传送门](事件处理 – React (reactjs.org))
组件与事件绑定
本章包含以下内容:
- React 中的组件
- 为组件绑定事件
- this 的指向
- 向事件处理函数传参
React 中的组件
在 React 中,可以使用类的方式来声明一个组件。
class 类名 extends React.Component{
render(){
return (
// 一段 JSX
)
}
}
除了类组件,React 中还支持使用函数来创建组件,同样需要返回一段 JSX,来表示这个组件的 UI 是什么样的。
function 组件名(){
return (
// 一段 JSX
);
}
早期的函数组件被称之为无状态组件,一般仅仅用来做纯 UI 的展示,里面不会有复杂的逻辑。
但是从 React 16.8 推出 Hooks 后,现在更多的是使用函数组件了。
这不仅仅是语法的改变,同时也代表着整个 React 编程思想的一种转变。
为组件绑定事件
在 React 中绑定事件的写法如下:
<button onClick={activateLasers}>Activate Lasers</button>
在 React 中无法通过 return false 来阻止默认行为,所以只有使用 e.preventDefault 的方式来阻止默认行为。
function Form() {
function handleSubmit(e) {
e.preventDefault();
console.log('You clicked submit.');
}
return (
<form onSubmit={handleSubmit}>
<button type="submit">Submit</button>
</form>
);
}
如果是类组件,那么事件处理函数写作一个类方法。
class Welcome extends React.Component {
// 事件处理函数
eventHandler(e){
window.alert('Hello');
e.preventDefault();
}
render() {
return (
<a href="https://www.baidu.com/" onClick={this.eventHandler}>this is a test</a>
);
}
}
在 React 的事件处理函数中所传入的事件对象,是一个合成事件对象。
React 也提供了访问原生事件对象的方式。如下:
eventHandler(e){
e.nativeEvent // 原生事件对象
}
this 的指向
在react的类组件中,通过以下方法调用函数,this的值将会指向undefined
import React, { Component } from 'react'
//改变this指向
export default class ClassComp extends Component {
clickHandle(){
console.log(this);//这里打印出来是undefined
}
render() {
return (
<div>
{/* <a href="https://www.baidu.com/" onClick={(e)=>{e.preventDefault()}}>百度一下,你就知道了</a> */}
<button onClick={this.clickHandle}>按钮</button>
</div>
)
}
}
但这并不是react的问题,而是由于 JS 中 this 的特殊性,事件处理函数中的 this 并不会指向当前的组件,这就需要我们自行对 this 进行指向的修正。
这里介绍 3 种解决方式:
- 将事件处理函数修改为箭头函数
- 将事件绑定修改为箭头函数
- 使用 bind 方法来强制绑定 this 的指向
针对以上三种解决方法,现分别举例如下:
方法一:将事件处理函数修改为箭头函数
import React, { Component } from 'react'
//改变this指向
export default class ClassComp extends Component {
clickHandle=()=>{
console.log(this);//现在在浏览器中就会打印出当前组件实例
}
render() {
return (
<div>
{/* <a href="https://www.baidu.com/" 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);//现在在浏览器中就会打印出当前组件实例
}
render() {
return (
<div>
{/* <a href="https://www.baidu.com/" 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);//现在在浏览器中就会打印出当前组件实例
}
render() {
return (
<div>
{/* <a href="https://www.baidu.com/" onClick={(e)=>{e.preventDefault()}}>百度一下,你就知道了</a> */}
<button onClick={()=>this.clickHandle()}>按钮</button>
</div>
)
}
}
方法三:使用 bind 方法来强制绑定 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 href="https://www.baidu.com/" onClick={(e)=>{e.preventDefault()}}>百度一下,你就知道了</a> */}
<button onClick={this.clickHandle}>按钮</button>
</div>
);
}
}
向事件处理程序传参
另外还有一个非常重要的问题,就是如何向事件处理函数传递参数。
如果要传递参数,可以使用下面的两种方式来进行传参:
- 通过 bind 方法在绑定 this 指向时向事件处理函数进行传参
- 绑定事件时,通过书写箭头函数的形式来传参
举例来说:
案例一:绑定事件时,通过书写箭头函数的形式来传参
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 指向时向事件处理函数进行传参
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参数基于前一个状态来更新list,过滤掉要删除的项
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来绑定函数并传参,注意这里要返回一个新的函数 */}
<button onClick={this.deleteRow.bind(this, item.id)}>删除</button>
</li>
))}
</ul>
);
}
}
今天的笔记就写到这里了,每天进步一小步,日积月累,水滴石穿