zoukankan      html  css  js  c++  java
  • 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的指向解除了

  • 相关阅读:
    oracle 10g 共享服务器搭建
    Oracle:10053事件简述
    Asktom Oracle: Partition table and index .
    Oracle shared server配置
    Oracle:物化视图语法
    Asktom:Thanks for the question regarding "consistent gets Very puzzling".
    oracle嵌套表整理的学习资料
    非空闲等待事件之:db file sequential read(转)
    Asktom Oracle:How to multiplex single row into multiple rows
    Oracle:Not exists
  • 原文地址:https://www.cnblogs.com/zhaohongcheng/p/11235679.html
Copyright © 2011-2022 走看看