React 事件处理函数在不使用 bind() 的情况下工作

IT技术 reactjs
2021-05-02 01:05:14

我正在学习 React 并且遇到了事件处理程序。在 React 中,建议在将函数this用作事件处理程序之前将其绑定到但是,我没有绑定它,我仍然获得了所需的输出。下面是我的代码:

import React, { Component } from 'react';

class Experiment extends Component {
    constructor(props){
        super(props);

    }

    clickEvent(e){
            e.preventDefault();
            document.getElementById('change').innerHTML="This text changed";
        }

    render(){
        return(
            <div>
                <p id='change'>This paragraph will change</p>
                <button onClick={this.clickEvent}>Press me</button>
            </div>
            );
    }
}

export default Experiment;

如您所见,我尚未绑定clickEvent()this,但该onClick事件可以顺利运行。这是为什么?我以为我会遇到undefined错误或其他什么

3个回答

这样做的原因是因为您没有在 clickEvent 函数中使用“this”来引用任何内容。在 javascript 中,函数中的“this”变量指的是调用该函数的对象。

为了证明这一点,请尝试访问this.propsor this.state,它们将返回 undefined 因为您缺少.bind(this)

.bind() 将返回一个新函数,该函数将坚持给定的“this”上下文,无论从何处调用它。

const myObj = {
    name: 'John',
    testFunction: function() {
        console.log(this.name);
    }
};

const testFunction = myObj.testFunction;

myObj.testFunction(); // John
testFunction(); // undefined


const testFunctionBound = testFunction.bind(myObj);
testFunctionBound(); // John

作为上述 Jye Lewis 回答的理论旁注,以及对该主题的澄清。

有 3 种常规方法将上下文绑定到 react 中的函数:

  1. 绑定(通常在构造函数中)
  2. 带箭头的类字段/属性
  3. 渲染中的箭头

示例代码:

class ThisDemo extends Component {
  constructor(props) {
    super(props); 

    // 1. In constructor 
    this.onClick = this.onClick.bind(this);
  }

  // 2. Class field/property with arrow
  onClick = () => {  
  }

  render() {
    // 3. Arrow in render
    return (
      <button type="button" onClick={event => console.log(event)}>
        Pretty Button
      </button>
    ); 
  }
}
export default ThisDemo; 

阴晴圆缺

  1. 绑定(通常在构造函数中)
    • ups:无论 N 有多大,都在同一个原型上。
    • 缺点:污染构造函数
  2. 带箭头的类字段/属性
    • ups:非常方便,语法很好。对于 N 个组件,创建 N 个不同的函数。
    • downs:在某些情况下,性能损失。(N高)
  3. 渲染中的箭头
    • ups:可以通过简单的方式捕获事件,有利于执行逻辑,而无需为回调参数传递 props。
    • 缺点:您在每次渲染时都会传递一个新的内联箭头函数。总是一个新的引用,这可能会导致重新渲染。

智慧

如果你要传递函数,你应该只绑定 with.bind() 或箭头函数。

带箭头的类字段/属性很方便,但如果This.Demo组件很多,效率可能会很低

务实的,直到你不能。性能问题几乎从来都不是问题,它们将来可能会改变它的工作方式。

参考

  1. 这篇文章帮助我理解了不同的方法。
  2. 还有这个

您可以使用箭头函数而不是创建构造函数并同时调用super

bind 方法。

箭头函数没有自己的 this,但它具有封闭执行上下文的 this 值。箭头函数在词汇上绑定了它们的上下文,因此 this 实际上是指原始上下文。如果您要命名事物,那就称为词法范围。基本上,它使我们免于在代码中执行 .bind(this) 。请注意,这是 JS 中的一个实验性功能,这意味着它尚未被 ECMAScript 标准接受

所以,而不是这样做:

//with binding in a constructor and calling super method
class Experiment extends Component {
  constructor(props) {
    super(props); 

    // 1. In constructor 
    this.onClick = this.onClick.bind(this);
  }
...
}

您可以以更简洁的方式进行操作,如下所示:

  //with arrow 
  handleOnClick = product => {  
     ...
  }

在您的render方法中,您可以执行以下操作:

class Experiment extends Component {
  render() {
    return (
        <button onClick={ () => this.handleOnClick(product) } >
            Add new product
        </button>
    );
  }
}

在本文中阅读有关箭头函数的更多信息: