<button onclick="activateLasers()"> Activate Lasers </button>
React数据传递之组件内部通信的方法(2)
React 中的事件:
// 因为 jsx 中'{}'里面代表函数表达式,
// 所以传递给 onClick 的实际是函数 activateLasers 的函数体部分,
// 因此需要指定 this 指向,不然会报错
<button onClick={activateLasers}>
Activate Lasers
</button>
2.2.2 存在的坑
直接传递 function 作为 event handler 需要指定函数的执行环境,即需要手动绑定 this ,不然会报 this 为 undefined 的错。见下面的例子:
class App extends Component {
constructor(props) {
super(props);
this.state = {
isToggleOn: true,
};
// 手动绑定 this
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
// 如果不在 constructor() 方法中手动绑定 this,直接将其作为事件处理程序 this 为 undefined
console.log(this);
this.setState(prevState => ({
isToggleOn: !prevState.isToggleOn
}));
}
render() {
return (
<div className="App">
<button onClick={this.handleClick}>
{this.state.isToggleOn ? "on" : "off"}
</button>
</div>
);
}
}
2.2.3 为什么会有坑
React 官网 说这个锅要 JS 原生语法来背,其实不尽然,React 实在 JS 语法早已确定的情况下设计了这样的事件系统,如果一定要有人站出来背锅,他们五五分吧。
1, JS原生语法存在的问题
JS语法中有这样的规则:如果将一个函数的函数体(没有 () )赋值给另一个变量,函数体内部的 this 指向可能会发生变化。会不会变化取决于函数和被赋值的变量是否处于同一个作用域(相同的执行环境)中,但实际使用中,将一个函数赋值给相同作用域的变量没有意义,那样的话直接使用那个函数就好,没必要在赋值给另一个变量。
this 指向不发生改变的没有意义的例子(为了方便说明,直接使用 var 操作符):
var fn = function () {
console.log(this);
};
var a = fn;
fn(); // window
a(); // window
this 指向发生改变的例子:
var fn = function () {
console.log(this);
};
// 将函数体赋值给一个对象的属性,函数执行时 this 和定义时指向不同
var o = {
a: fn,
};
fn(); // window
o.a(); // o,即{a:f}
如果想要在将函数体赋值另一个变量的同时把原函数的 this 指向也一块赋值过去,就需要在赋值的过程中进行绑定 this 的操作,如下:
var fn = function () {
console.log(this);
};
// fn 在赋值的同时将内部的 this 打包一块赋值给了 a
var o = {
a: fn.bind(this),
};
fn(); // window
o.a(); // window
通常在将函数体赋值给变量的时候为了避免 this 出错,都会进行 绑定执行环境的操作 ,典型的例子是 var bindId = document.getElementById.bind(document)
