reactjs 为什么需要在构造函数中绑定函数

y3bcpkx1  于 2023-01-02  发布在  React
关注(0)|答案(6)|浏览(149)

我有一个关于此代码的问题:https://github.com/reactjs/redux/blob/master/examples/async/containers/App.js
具体而言:

constructor(props) {
    super(props)
    this.handleChange = this.handleChange.bind(this)
    this.handleRefreshClick = this.handleRefreshClick.bind(this)
  }

我想这是一个两部分的问题。
1.为什么我需要将handle change设置为this.handleChange =类的示例,我不能只使用handleChange的静态函数,然后在onClick={handleRefreshClick}>类中直接调用它吗?
1.我不知道这是怎么回事:this.handleRefreshClick.bind(this)
谢啦,谢啦

mepcadol

mepcadol1#

以相反的顺序回答...

  1. this.handleRefreshClick.bind(something)返回一个新函数,其中对this的引用将引用something。这是一种保存this当前值的方法,该值在调用构造函数期间处于作用域中,以便以后调用函数时可以使用。
    1.如果函数不需要访问组件的状态,那么当然不需要绑定它们。
    支持将这些行添加到构造函数的论据是,新的绑定函数对于类的每个示例只创建一次。
onClick={this.handleRefreshClick.bind(this)}

或(ES6):

onClick={() => this.handleRefreshClick()}

但是这些方法中的任一个将在每次重新呈现组件时创建新函数。

gg0vcinb

gg0vcinb2#

这样做的原因是,把this关键字绑定到那个对象,就像Tom说的,从类调用函数并不意味着它是在创建函数的对象的上下文中调用的.
我想您可能会感到困惑,因为在React示例/教程中,使用React.createClass()DOES会自动为您绑定this。因此,您可能会想知道为什么React.createClass()会自动绑定this,但不会使用ES6类语法。
这是因为React不想扰乱ES6规范(绑定this到来自其类的函数不在ES6类规范中),但同时,希望给用户提供ES6类语法的便利。
Github issue
希望这能解释为什么会发生这种情况。

epggiuax

epggiuax3#

this取决于如何调用函数,而不是如何/在何处创建函数。
当你看代码的时候,你会看到两个“this”,为什么?看起来很奇怪,对吗?问题不在于它看起来如何,而在于它如何被调用。
你基本上是在说,嘿,当有人打电话给你的时候,记住this是指这个类,而不是别的什么。
当有人这样称呼你的类:x.yourClass().bind(this)您是说this不是x,而是类本身(包含属性和状态等)。
快速注意,即使当你直接调用yourClass()这样的类时,你实际上是在浏览器 * 上调用window.yourClass() *,这也是为什么在这种情况下 this 是窗口。

z5btuh9x

z5btuh9x4#

这两个函数handleChange和handleRefreshClick作为属性传递给其他组件,
它们被绑定到这个函数,因为当子组件调用这些函数时,它们总是与APP上下文一起执行。
您可以从类中删除这些函数,但仍然需要绑定它,因为您将更新APP的某些部分

s4n0splo

s4n0splo5#

这里的所有答案都很好,但为了清楚起见:
1.我不知道这是怎么回事:第一个月
我认为一个例子最能说明行为上的差异。

// Class where functions are explicitly bound to "this" specific object
var Bindings = class {
  constructor() {
    this.Firstname = "Joe"
    this.Surname = "Blow"
    this.PrettyPrint = this.PrettyPrint.bind(this)
    this.Print = this.Print.bind(this)
  }

  Print(inputStr) {
    console.log(inputStr)
    console.log(this)
  }

  PrettyPrint() {
    this.Print(`${this.Firstname} ${this.Surname}`)
  }
}

// Class where "this" context for each function is implicitly bound to 
//  the object the function is attached to / window / global
//  identical class, except for removing the calls to .bind(this)
var NoBindings = class {
  constructor() {
    this.Firstname = "Joe"
    this.Surname = "Blow"
  }

  Print(inputStr) {
    console.log(inputStr)
    console.log(this)
  }

  PrettyPrint() {
    this.Print(`${this.Firstname} ${this.Surname}`)
  }
}

var bindings = new Bindings()
var noBindings = new NoBindings()

bindings.PrettyPrint() 
// > "Joe Blow"
// > Object { Firstname: "Joe", Surname: "Blow", PrettyPrint: PrettyPrint(), Print: Print() }

noBindings.PrettyPrint() 
// > "Joe Blow"
// > Object { Firstname: "Joe", Surname: "Blow" }

// noBindings has both functions & everything works as we expect, 
// if this is all you're doing, then there's practically little difference,
// but if we separate them from the original "this" context...

var b = { PPrint: bindings.PrettyPrint }
var nb = { PPrint: noBindings.PrettyPrint }

b.PPrint()
// > "Joe Blow"
// > Object { Firstname: "Joe", Surname: "Blow", PrettyPrint: PrettyPrint(), Print: Print() }
// PPrint calls "PrettyPrint" where "this" references the original "bindings" variable
// "bindings" has a function called "Print" which "PrettyPrint" calls

try {
  nb.PPrint() 
} catch (e) {
  console.error(e);
}
// > Uncaught TypeError: this.Print is not a function
// PPrint calls "PrettyPrint" where "this" references the new "nb" variable 
// due to different "this" context, "nb" does not have a function called "Print", so it fails

// We can verify this by modifying "bindings" and seeing that it's reflected in "b"
bindings.Surname = "Schmo"
b.PPrint()
// > "Joe Schmo"
// > Object { Firstname: "Joe", Surname: "Schmo", PrettyPrint: PrettyPrint(), Print: Print() }

// We can also add a "Print" method to "nb", and see that it's called by PrettyPrint
nb.Print = function(inputStr) { console.log(inputStr); console.log(this) }
nb.PPrint()
// > undefined undefined
// > Object { PPrint: PrettyPrint(), Print: Print(inputStr) }

// The reason we get "undefined undefined", 
//  is because "nb" doesn't have a Firstname or Surname field.
//  because, again, it's a different "this" context
6ovsh4lw

6ovsh4lw6#

我个人在构造函数中绑定函数,这样它们的引用在每次重新呈现时都不会改变。
如果你向只读的子节点传递函数,而这些子节点的属性没有改变,你就不需要更新,这一点就特别重要,我使用react-addons-pure-render-mixin来实现。
否则,在每个父级的重新呈现中,将发生绑定,新的函数引用将被创建并传递给子级,子级将认为 prop 已更改。

相关问题