react的事件处理为什么要bind this 改变this的指向?
Posted zhaohongcheng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react的事件处理为什么要bind this 改变this的指向?相关的知识,希望对你有一定的参考价值。
react的事件处理会丢失this,所以需要绑定,为什么会丢失this?
首先来看摘自官方的一句话:
You have to be careful about the meaning of this in JSX callbacks. In javascript, class methods are not bound by default.
这句话大概意思就是,你要小心jax回调函数里面的this,class方法默认是不会绑定它的
让我十分疑惑,在我的知识范围理解中,class是es6里面新增的方法,不就用来继承原有对象上的属性和方法创建新的对象吗?就是代替原来的构造函数的一种更清晰的方式,为什么就不会绑定this呢?
可是查阅了一些es6的文档,并不是这样的啊,和class方法没啥关系吧,为什么要它背锅呢?
class Toggle extends React.Component constructor(props) super(props); this.state = isToggleOn: true; // This binding is necessary to make `this` work in the callback this.handleClick = this.handleClick.bind(this); handleClick() this.setState(prevState => ( isToggleOn: !prevState.isToggleOn )); render() return ( <button onClick=this.handleClick> //这里调用的this也能拿到啊?? this.state.isToggleOn ? ‘ON‘ : ‘OFF‘ //这里的this为什么没问题? </button> );
这是官网上的一段代码,如果是是因为class的关系,handleClick里面拿不到this,那为什么render里面能拿到this,所以和class根本没关系吧本来就能拿到,那问题出现在哪里,为什么拿不到?
先看看解决办法
第一种,在constructor里面用bind绑定this
constructor(props) super(props); this.state = isToggleOn: true; // This binding is necessary to make `this` work in the callback this.handleClick = this.handleClick.bind(this);
第二种,声明方法的时候使用箭头函数
handleClick = () => this.setState(prevState => ( isToggleOn: !prevState.isToggleOn ));
第三种,调用的时候使用箭头函数
render() return ( <button onClick= () => this.handleClick > this.state.isToggleOn ? ‘ON‘ : ‘OFF‘ </button> );
这个时候我想起了原生dom绑定click的方法
<button onclick ="handleClick()">点我</button>
两者比较,我发现了个区别,原生的绑定方法事件名后面多了个()
于是我尝试着在react里面的事件加一个()
render() return ( <button onClick= this.handleClick() > this.state.isToggleOn ? ‘ON‘ : ‘OFF‘ </button> );
就像上面这样,然后我发现,无论我怎么点,都不会触发这个方法了,再细心点,就发现,在渲染的时候,就调用了一次,而且仅此一次,再也不能调用了.
原因是jsx语法,渲染的时候会把里面包裹的代码先解析一遍,因为如果加了括号,直接就执行了里面的函数,就没有东西了,但是这个时候,this是可以拿到的
class App extends Component handleClick() console.log(this); //下面调用加了(),这个时候发现,this是可以拿到的 render() return ( <div className="App"> <button onClick=this.handleClick()>点我</button> //这里加了括号的 </div> );
好像问题越来越明朗了,为啥会拿不到,和class没有关系,完全是因为react自己封装的东西,先会把里面的代码解析一遍,于是大概就是下面这种情况了
const obj = num:1 obj.handleClick = function () console.log(this); console.log(eval(obj.handleClick )); // f() console.log(this) react对的解析 (eval(obj.handleClick))() //onclick触发点击事件 这里输出this是window,所以就等于丢失了this指向 console.log(eval(() => obj.handleClick() )); // () => obj.handleClick() react对的解析 (eval(() => obj.handleClick()))() //onclick触发点击事件 这里输出this还是obj,所以this就保留了
所以问题出在react对的解析会把this的指向解除了
以上是关于react的事件处理为什么要bind this 改变this的指向?的主要内容,如果未能解决你的问题,请参考以下文章
(转)React事件处理函数必须使用bind(this)的原因