当你使用 ES6 class
语法定义一个组件的时候,通常的做法是将事件处理函数声明为 class
中的方法。例如,下面的 Toggle
组件会渲染一个让用户切换开关状态的按钮:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>事件处理中this</title>
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<!-- <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script> -->
<!-- <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
class Toggle extends React.Component {
constructor(props) {
super(props)
this.state = { isToggleOn: false }
}
handleClick() {
console.log(this) // undefined
this.setState((state, props) => ({
isToggleOn: !state.isToggleOn
}))
// 大括号外需要加小括号
// 原因:因为箭头函数写法()=>{}后面的大括号作为函数体,
// 如果上面(state, props) => {isToggleOn: !state.isToggleOn}不加上()则大括号里面isToggleOn: !state.isToggleOn将作为函数体执行,明显里面内容不是执行语句。
// 如果加上小括号,(state, props) => ({isToggleOn: !state.isToggleOn})的函数体就相当于返回一个{isToggleOn: !state.isToggleOn}对象
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'on' : 'off'}
</button>
)
}
}
ReactDOM.render(
<Toggle />,
document.getElementById('root')
)
</script>
</body>
</html>
当浏览器执行上述脚本代码时会发生如下错误:
错误产生的原因是因为onClick={this.handleClick}
仅仅传入了函数的引用,并没有绑定执行函数this
指向,所以this
值是undefined
,this.setState
就找不到setState
。
既然没有绑定函数的this
指向,我们有以下两种方式指定this
:
- 1、使用
bind
绑定this
constructor(props) {
super(props)
this.state = { isToggleOn: false }
this.handleClick = this.handleClick.bind(this)
}
或者
render() {
return (
<button onClick={this.handleClick.bind(this)}>
{this.state.isToggleOn ? 'on' : 'off'}
</button>
)
}
- 2、回调函数采用调用式
render() {
return (
<button onClick={() => this.handleClick()}>
{this.state.isToggleOn ? 'on' : 'off'}
</button>
)
}
handleClick
函数调用者是this(Toggle对象)
,所以函数内部this
也指向Toggle
对象
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。