写在前面
React官网事件处理
React 元素的事件处理和 DOM 元素的很相似,但是语法上有两点不同:
- React 事件的命名采用小驼峰式(camelCase),而不是纯小写,如 onClick、onKeyPress等。
- 使用 JSX 语法时你需要传入一个 函数 作为事件处理函数,而不是一个字符串。
- 在 React 中另一个不同点是你不能通过返回 false 的方式阻止默认行为。你必须显式的使用 preventDefault 。
1. 类组件的事件处理
类组件中的事件绑定比较复杂,因为其事件处理函数里面涉及到 this 这个变量指针。
类组件中方法函数的定义里若访问类内的变量基本都使用到了 this
关键字。React 中的类组件被渲染到页面后,就完全转化为了 DOM 元素,DOM 元素的事件处理函数就是定义在类组件内的方法函数,那么 DOM 元素在事件触发后调用相应的事件处理函数时就会碰到里面的 this
,但此时是 window 调用的事件处理函数,函数里的 this
就是指向的 window
或者是 undefined
, 查找 window
里并无对应的变量定义,就会出现 undefined
的情况。因此在 React 的类组件中的方法的定义里含有 this
关键字的,就必须绑定 this
。
1.1 普通绑定方法
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// 为了在回调中使用 `this`,这个绑定是必不可少的
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</button>
);
}
}
1.2 class fields 绑定方法(Create React App 默认启用此语法。)
ES6 新语法中的箭头函数是不支持 this
的,因此若在箭头函数里使用 this
,就会从其所在的外层将 this
作为一个变量去找,从而实现将 this
用内部使用外部变量的闭包方式绑定 this
。
class LoggingButton extends React.Component {
constructor(props) {
super(props);
}
// 此语法确保 `handleClick` 内的 `this` 已被绑定。
handleClick = () => {
console.log('this is:', this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
上述方法其实是一种语法糖。最原始的写法是如下:
class LoggingButton extends React.Component {
constructor(props) {
super(props);
this.handleClick = () => {
console.log('this is:', this);
}
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
1.3 回调中使用箭头函数
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// 此语法确保 `handleClick` 内的 `this` 已被绑定。
return (
<button onClick={() => this.handleClick()}>
Click me
</button>
);
}
}
1.4 带参数的事件绑定
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
2. 函数组件的事件处理
函数组件的事件绑定比较简单,因为其事件处理函数的调用不含有 this
。直接在类组件内定义事件处理函数即可。
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}