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的指向?的更多相关文章

  1. React中的事件处理为什么要bind this?

    个人总结: 问: 请给我讲一下React中的事件处理为什么要bind this? 答: 好的,比如说我写了一个类组件,有个onClick属性 ,onClick={ this.fun },如果不bind ...

  2. bind改变this的指向

    <script type="text/javascript"> var Hello = function(){ this.setT = function(){ wind ...

  3. this指向详解及改变它的指向的方法

    一.this指向详解(彻底理解js中this的指向,不必硬背) 首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是 ...

  4. 改变this的指向问题;

    用call()和apply()改变this的指向,那什么时候用this呢?(构造函数),那为什么要用构造函数呢?(为了生成对象). 1.解决函数内this指向的问题 (1)var that/_this ...

  5. JavaScript中this的用法 及 如何改变this的指向

    要懂得JavaScript中this的用法,首先需要知道,JavaScript中的作用域相关知识. var fun = function(){ var flag = 1; console.log(fl ...

  6. 有关call和apply、bind的区别及this指向问题

    call和apply都是解决this指向问题的方法,唯一的区别是apply传入的参数除了其指定的this对象之外的参数是一个数组,数组中的值会作为参数按照顺序传入到this指定的对象中. bind是解 ...

  7. 3种方法改变this的指向

    <body>     <div style="width: 200px;height: 200px;hotpink;"></div>     & ...

  8. React事件处理函数的bind复用和name复用

    一.bind复用 <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset=&qu ...

  9. react篇章-事件处理

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title&g ...

随机推荐

  1. Educational Codeforces Round 78 (Rated for Div. 2) C. Berry Jam

    链接: https://codeforces.com/contest/1278/problem/C 题意: Karlsson has recently discovered a huge stock ...

  2. luogu p2622关灯问题II

    luogu p2622关灯问题II 题目描述 现有n盏灯,以及m个按钮.每个按钮可以同时控制这n盏灯--按下了第i个按钮,对于所有的灯都有一个效果.按下i按钮对于第j盏灯,是下面3中效果之一:如果a[ ...

  3. 【BZOJ3837】[PA2013]Filary

    [BZOJ3837][PA2013]Filary 题面 darkbzoj 题解 考虑到模数为\(2\)时答案至少为\(\frac n2\),这是我们答案的下界. 那么我们对于任意的一个数,它们答案集合 ...

  4. docker 部署 jenkins

    建议使用的Docker映像是jenkinsci/blueocean image(来自 the Docker Hub repository). 该镜像包含当前的长期支持 (LTS) 的Jenkins版本 ...

  5. ROS+gre over ipv6,在ipv6的基础上建立GRE隧道

    感谢群众大神 @镜花水月全程技术支持.感谢! 环境: 1.阿里云华北5,申请ipv6测试,申请ECS带ipv6公网ip 2.为了便于测试便捷,在vultr创建2.5美元的vps,带ipv6 对了,测试 ...

  6. Java小学四则运算

    本次作业要求来自:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2166 github远程仓库的地址:https://github.c ...

  7. 修改Mac新建文件、文件夹的默认权限

    Mac 新建文件和文件夹默认 当前用户才有读和写的权限,其他用户只有读的权限 修改Mac新建文件.文件夹的默认权限的步骤如下: 1.打开 “终端” 2.在终端中输入以下命令: 创建文件时,从默认值(对 ...

  8. VisualStudio ------- vs发布软件

    上线的系统和自己做的系统有什么区别 上线的没有源代码,没有实体层,数据库访问层  业务逻辑层 只有表现层  而且也也没有    .cs 和 .psd   文件,这样就不能修改系统代码 他们都在 Web ...

  9. Python3版本号比较代码实现

    一.版本号比较的困难 不能直接以字符串形式进行比较:对于1.3和1.4直接以字符串进行比较是可以正确得出1.4比1.3大:但如果是1.3和1.14还直接进字符串比较那就是1.3比1.14大那就不对了. ...

  10. [转帖]HashMap、HashTable、ConcurrentHashMap的原理与区别

    HashMap.HashTable.ConcurrentHashMap的原理与区别 http://www.yuanrengu.com/index.php/2017-01-17.html 2017年1月 ...