class Timer extends React.Component {
constructor(props) {
super(props);
this.state = { seconds: 0 };
}
tick() {
this.setState(prevState => ({
seconds: prevState.seconds + 1
}));
}
componentDidMount() {
this.interval = setInterval(() => this.tick(), 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
return (
<div>
Seconds: {this.state.seconds}
</div>
);
}
}
ReactDOM.render(<Timer />, mountNode);
() => this.tick(),这里为什么不能改为this.tick()?谢谢
使用React.component
这种方法生成一个组件Timer的时候,用React的方式绑定事件处理函数,事件处理函数并没有绑定在当前组件
Timer
上的, 因此我们要这么写:
handleClick
方法里面的this.setState
中的this才是指向当前组件。
同理的,我们知道setInterval
的里面的回调函数中的this
是指向windows
对象的,直接写this.tick()
肯定是不对的。而使用箭头函数的方式,首先箭头函数是没有自己的this的,箭头函数里面的this是定义时所在对象,即Timer
组件,由于绑定在了当前组件,所以方法的调用和方法的执行,其中的this都正确的指向组件。
另外,绑定事件也可以这么写:
{ this.handleClick() } }>
个人理解,不喜勿喷
应该setInterval使用箭头函数能够使用this,但是tick中得作用域是window 所以你再绑定tick方法时候必须要使用箭头函数,或者bind给函数绑定this
先来看个this指向问题的栗子:
var obj = {
hello(){
console.log( this )
}
}
obj.hello() // this === obj
var refHello = obj.hello()
refHello() // this === window
先确保能看懂,如果不清楚this指向的问题,可以先移步:this 的工作原理。理解清楚了,往下看。
回到你的问题:
/*
** 当this.tick() 执行的时候
** 函数体中的this会去找当前是谁执行这个函数的,本例是.tick()符号点的前面的那个对象,也就是this
** 而this等于componentDidMount中的this(箭头函数不改变this,向上找),也就是当前component实例
** 所以this能查找正确
*/
this.interval = setInterval(() => this.tick(), 1000);
// 如果改成如下
this.interval = setInterval( this.tick , 1000);
// 相当于如下
var anonyFunc = this.tick
this.interval = setInterval( anonyFunc , 1000);
/*
** 当一秒钟之后,执行的就是anonyFunc()
** anonyFunc函数体会去查找this,发现是函数调用(anonyFunc()),而不是对象的方法调用
** 那这里的this指向就是全局对象了,也就是window
*/
看到这里,你应该能清楚为什么不能
了。
不过,既然说到这了,我就在展开一下。react官方推荐的在构造方法里面通过bind绑定的方式:
class A extends React.Component {
constructor( props ) {
super( props )
this.methodXXX = this.methodXXX.bind( this )
}
methodXXX(){
// do some thing
}
render(){
return <div onClick={ this.methodXXX }></div>
}
}
render中的onClick={ this.methodXXX }
,其实jsx翻译之后,类似于:
var clickFunc = this.methodXXX
var div = document.querySelector('div')
div.addEventListener( 'click' , clickFunc )
后续click事件发生其实就是函数调用
了,但是因为事先在constructor
构造函数中通过bind绑定过了this,所以虽然是函数调用
但是也能成功找到预期的this。
每次显式的写这种bind方法,是一件痛苦的事情,好在有个提案:ES proposal: class fields。
能让我们这么写:
class A extends React.Component {
constructor( props ) {
super( props )
}
methodXXX = () => {
// do some thing
}
render(){
return <div onClick={ this.methodXXX }></div>
}
}
利用箭头函数,帮我们隐式绑定了this,可以愉快的赋值了,妈妈再也不怕我弄丢this了。这个写法react官方也有提及:Class Properties
以上,all