react 的生命周期方法是自动绑定的吗?如果不是,我们应该用 .bind(this) 绑定它们吗?

IT技术 javascript reactjs ecmascript-6 es6-class
2021-04-28 06:07:07

我认为标题是非常自我描述的。

我已经使用类表示法构建了 React 组件,我注意到 whilehandleSomething必须手动绑定到thisrendercomponentWillMount不要。方法是否this已经绑定为了符号的一致性,可以手动绑定吗?

1个回答

理解 JavaScript 中的“this”

函数中的“this”关键字由函数的执行范围决定。例如,调用 with 时thisin将是someFunctionobj.someFunction()obj

一个更具体的例子:

function handleClick() {
    console.log(this.state.value);
}

var state = { value: 1 }; // declare a var in window
console.log("handleClick()");
handleClick(); // Logged 1. The 'this' in the method will be window, because the method is called in window


var obj = {
  state: { value: 2 },
  handleClick: function() {
    console.log(this.state.value);
  },
};
console.log("obj.handleClick();");
obj.handleClick(); // Logged 2. The 'this' is referred to obj because the method is called in obj.

// let's reassign the function to a temp var in window
var temp = obj.handleClick;
console.log("temp()");
temp(); // Logged 1. The 'this' in the function is referred to window because the method is called in window.
console.log("window.temp()");
window.temp(); // this is equal to the one above.

console.log("temp.bind(obj)");
temp.bind(obj)(); // Logged 2. Bind the method and call the method, so the 'this' in the function is referred to obj.

console.log("temp.bind(this)");
temp.bind(this)(); // Logged 1. Since this in the executing scope is window. This effectively is the same calling in this.

console.log("temp.bind(window)");
temp.bind(window)(); // Logged 1. This is equal to the one above.

在这里试试:https : //codepen.io/anon/pen/OvOpEa?editors=0012

关于此的博客文章:https : //hackernoon.com/understanding-javascript-the-this-keyword-4de325d77f68

回到你的问题

如果您查看render, componentWillMount, 并handleSomething在您的类中定义,就会很明显为什么需要将处理程序绑定到this

使成为

// Rerender
ReactCurrentOwner.current = workInProgress;
var nextChildren = void 0;
{
  ReactDebugCurrentFiber.setCurrentPhase('render');
  nextChildren = instance.render();
  if (debugRenderPhaseSideEffects) {
    instance.render();
  }
  ReactDebugCurrentFiber.setCurrentPhase(null);
}

这就是 react call 的方式redner(),其中实例是具有状态、props等的对象实例。您可以通过在渲染方法中放置断点并返回调用堆栈来轻松尝试。

处理东西

例如,如果你这样定义你的类,handleSomething作为onClick按钮回调方法。

class Button extends Component {
  handleSomething() {
    // 'this' will be undefined.
  }

  render() {
    return (<button onClick={this.handleSomething}>Test</button>);
  }
}

如果您单击按钮,这就是 react 调用 onClick 处理程序方法的方式。

  function callCallback() {
    fakeNode.removeEventListener(evtType, callCallback, false);
    // This is where react calls your method.
    func.apply(context, funcArgs);
    didError = false;
  }

其中funcis handleSomething,并且context通常undefined在我的调试经验中,并且funcArgs是在函数中传递的参数。

apply类似于bind. 第一个参数用于指定this函数的,第二个参数是要传递给函数的参数数组。

有关更多信息,请参阅 MDN applyhttps : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

在这种情况下,方法handleSomething是用undefinedas调用的this因此,如果您没有绑定该方法,您this将是undefined.

我注意到虽然 handleSomething 必须手动绑定到这个,render 和 componentWillMount 不需要。方法是否已经绑定到这个?

它们是用您的类的实例调用的,因此它们已经this作为您的实例而无需使用bind. 我想你可以说它已经绑定到this.

为了符号的一致性,可以手动绑定吗?

你不需要绑定thisreact 的生命周期方法。如果你真的想要,我想你可以结合这些方法this,以及(可能有一些副作用,我不知道,因为我真的不看,能深入到他们的来源),但是这就像在做obj.handleClick.bind(obj)();,而不是的obj.handleClick();这是不必要的,并且会花费一些时钟周期来做一些不需要的事情。