React中事件的处理
React中事件的处理
React 中使用 onClick 类似的写法来监听事件,注意 this 绑定问题 React 里严格遵循单项数据流,没有数据双向绑定,所以要处理两件事,第一是元素本身值的赋值,第二是值改变以后的事件,例如输入框需要设置 value 和 onChange 。
import React, { Component } from "react";
export default class CardSample extends Component {
//状态的初始化一般放在构造器中
constructor(props) {
super(props);
this.state= {
text: '',
goods: []
}
//为了在回调中使用'this',这个绑定式必不可少的
this.textChange = this.textChange.bind(this);
}
//当input的值text发生变化的时候,调用textChange去切换input的值
textChange (event) {
this.setState({
text: event.target.value
})
}
addGoods= ()=> {
this.setState(prevstate => {
// prevstate.goods.push({
// id: prevstate.goods.length + 1,
// name: prevstate.text
// })
// react官方希望传入与返回的对象不应该是同一个对象,所以上面的写法需要改进
return {
goods: [
...prevstate.goods, //获取原来的商品填充到新的数组goods中
{
id: prevstate.goods.length + 1,
name: prevstate.text
}
]
}
})
}
render() {
return (
<div>
{/*事件处理*/}
<div>
<input type='text' value={ this.state.text } onChange={ this.textChange }/>
<button onClick={ this.addGoods }> 添加商品 </button>
</div>
<ul>
{
this.state.goods.map((good)=>
return <li key={ good.id }>{ good.name }</li>
)
}
</ul>
</div>
)
}
}
注意:
- React 事件的命名采用小驼峰式(camelCase),而不是纯小写。且事件名称之后不能加 (),否则会直接执行
- 不能通过返回 false 的方式阻止默认行为。必须显式的使用 preventDefault
- 必须谨慎对待 JSX 回调函数中的 this ,在 JavaScript 中,class(类) 的方法默认不会绑定 this 。如果忘记绑定 this.textChange 并把它传入了 onChange ,当调用这个函数的时候 this 的值为 undefined。如果觉得使用 bind 麻烦,还可以使用 箭头函数。
一、React组件中的事件处理函数
1、constructor函数中bind
class ReactEvent extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log('Click');
}
render() {
return <button onClick={this.handleClick}>Click Me</button>;
}
}
2、使用箭头函数
(1)render中使用箭头函数
class ReactEvent extends Component {
handleClick() {
console.log('Click');
}
render() {
return <button onClick={() => this.handleClick()}>Click Me</button>;
} }
(2)使用class fields语法
class ReactEvent extends Component {
//此函数会被绑定到ReactEvent类的实例
handleClick = () => {
console.log('Click');
}
render() {
return <button onClick={this.handleClick}>Click Me</button>;
} }
(3)在render中使用bind
class ReactEvent extends Component {
handleClick() {
console.log('Click');
}
render() {
return <button onClick={this.handleClick.bind(this)}>Click Me</button>;
} }
二、几种方式比较
影响 |
constructor函数中bind |
使用class fields语法 |
render中使用箭头函数 |
在render中使用bind |
render时生成新函数 |
否 |
否 |
是 |
是 |
性能 |
无影响 |
无影响 |
有影响 |
有影响 |
可直接携带参数 |
否 |
否 |
是 |
是 |
简洁性 |
不好 |
好 |
好 |
好 |
三、事件处理中传参
在开发当中,经常遇到对一个列表做操作,可能包含删除,修改,查看。这时候绑定事件就需要传参,通常为id。
1、直接传递参数
2、使用data属性
例如:
import React, { Component } from "react";
export default class EventComponet extends Component {
constructor(props) {
super(props);
this.state= {
list: [
{
id: 1,
msg: 'AAA'
},
{
id: 2,
msg: 'BBB'
},
{
id: 3,
msg: 'CCC'
}
]
}
}
handleClick(e) {
console.log(e.target.dataset.id)
}
render() {
const { list } = this.state
return (
<div>
{
list.map(item=><button data-id={ item.id } key={ item.id} onClick={this.handleClick}>{item.msg}</button>)
}
</div>
)
}
}
这里不强制推荐使用哪一种,对于各个团队来说,可以根据项目,选择自己团队的事件绑定方式。
因为箭头函数的简洁性,在公司项目中,通常使用class fields 定义箭头函数来绑定事件。当需要传参的时,单个参数传递使用data属性传参。多个参数传递时,采用拆分子组件的方式回调传参。