如何在 React 上正确地将 onclick 处理程序绑定到 `this`

IT技术 javascript reactjs this
2021-03-03 15:26:05

解释为什么这不是重复的:我的代码已经在工作,我已将其作为注释包含在内。问题是为什么this当我将它包含到单击处理程序函数时上下文会发生变化。
我正在尝试在 React 中创建一个计算器项目。目标是将 onclick 处理程序附加到数字按钮,以便数字显示在计算器显示区域上。如果将处理程序直接写入 render 方法,则它可以正常工作,但是,如果我从 ComponentDidMount 尝试,我会收到错误消息this.inputDigit is not a function如何this.inputDigit(digit)正确绑定

import React from 'react';
import './App.css';

export default class Calculator extends React.Component {

// display of calculator initially zero
state = {
  displayValue: '0'
}

//click handler function
inputDigit(digit){
  const { displayValue } = this.state;
  this.setState({
    displayValue: displayValue+String(digit)
  })
}

componentDidMount(){

  //Get all number keys and attach click handler function
  var numberKeys = document.getElementsByClassName("number-keys");
  var myFunction = function() {
    var targetNumber = Number(this.innerHTML);
    return this.inputDigit(targetNumber); // This is not working
  };
  for (var i = 0; i < numberKeys.length; i++) {
    numberKeys[i].onclick = myFunction;
  }

}

render() {
  const { displayValue } = this.state;
  return (
    <div className="calculator">
      <div className="calculator-display">{displayValue}</div>
      <div className="calculator-keypad">
        <div className="input-keys">

          <div className="digit-keys">
            {/*<button className="number-keys" onClick={()=> this.inputDigit(0)}>0</button> This will Work*/}}
            <button className="number-keys">0</button>                
            <button className="number-keys1">1</button>
            <button className="number-keys">2</button>
            <button className="number-keys">3</button>
            <button className="number-keys">4</button>
            <button className="number-keys">5</button>
            <button className="number-keys">6</button>
            <button className="number-keys">7</button>
            <button className="number-keys">8</button>
            <button className="number-keys">9</button>
          </div>
        </div>          
      </div>
    </div>
  )
 }
}
2个回答

那是因为你在一个没有绑定的函数中编写它,

利用

var myFunction = function() {
    var targetNumber = Number(this.innerHTML);
    return this.inputDigit(targetNumber); 
  }.bind(this);

或者

const myFunction = () => {
    var targetNumber = Number(this.innerHTML);
    return this.inputDigit(targetNumber); 
}

在此之后,您还需要绑定 inputDigit 函数,因为它也使用 setState

//click handler function
inputDigit = (digit) => {
  const { displayValue } = this.state;
  this.setState({
    displayValue: displayValue+String(digit)
  })
}

由于您还想使用按钮文本,在这种情况下,您应该使用一个单独的变量来代替this调用 inputDigit 函数,例如

class Calculator extends React.Component {

// display of calculator initially zero
state = {
  displayValue: '0'
}

//click handler function
inputDigit(digit){
  const { displayValue } = this.state;
  this.setState({
    displayValue: displayValue+String(digit)
  })
}

componentDidMount(){

  //Get all number keys and attach click handler function
  var numberKeys = document.getElementsByClassName("number-keys");
  var that = this;
  var myFunction = function() {
    var targetNumber = Number(this.innerHTML);
    console.log(targetNumber);
    return that.inputDigit(targetNumber); // This is not working
  };
  for (var i = 0; i < numberKeys.length; i++) {
    numberKeys[i].onclick = myFunction;
  }

}

render() {
  const { displayValue } = this.state;
  return (
    <div className="calculator">
      <div className="calculator-display">{displayValue}</div>
      <div className="calculator-keypad">
        <div className="input-keys">

          <div className="digit-keys">
            {/*<button className="number-keys" onClick={()=> this.inputDigit(0)}>0</button> This will Work*/}
            <button className="number-keys">0</button>                
            <button className="number-keys">1</button>
            <button className="number-keys">2</button>
            <button className="number-keys">3</button>
            <button className="number-keys">4</button>
            <button className="number-keys">5</button>
            <button className="number-keys">6</button>
            <button className="number-keys">7</button>
            <button className="number-keys">8</button>
            <button className="number-keys">9</button>
          </div>
        </div>          
      </div>
    </div>
  )
 }
} 

ReactDOM.render(<Calculator/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

我将 targetNumber 设为 NaN
2021-04-23 15:26:05
等待,将创建一个工作片段并在几分钟内发布
2021-04-25 15:26:05
实际上需要添加数字以显示为字符串,所以我删除了Number,然后我得到了undefined.
2021-05-01 15:26:05
Number(this.innerHTML)返回什么
2021-05-06 15:26:05
它正在返回 NaN
2021-05-07 15:26:05

在构造函数中绑定

constructor(props) {
    super(props);
    this.inputDigit = this.inputDigit.bind(this);
}
OP 使用"plugins": ["transform-class-properties"] 不必这样做。绑定每个组件方法可能会变得混乱,这就是为什么它们使用state = 而不是this.state在构造函数中。
2021-04-23 15:26:05
state =不在构造函数中,您不需要为每个方法都这样做。只是您需要执行回调或任何受上下文更改影响的函数。
2021-05-12 15:26:05