目前,我正在参加有关Udemy的关于React的课程。
现在的选择是关于传递方法引用。因此,基本上讲师将方法引用作为道具传递给App.js的render方法内的Person标签。在Person组件中,单击按钮时将执行switchNameHandler,而在修改输入文本字段时将执行nameChangedHandler。
因此,课程讲师使用.bind()方法。我已经研究了bind()方法的作用。但是在当前示例中,我有两个问题:
在当前示例中,此关键字指的是两个(App.js中的第二个人标签=> click值)?据我了解的代码,他采取this.switchNameHandler类的当前方法,并将其再次绑定到当前类(我知道没有道理)吗?这两个处理程序方法是该类的一部分,对我而言这没有意义,因为您通常将类外部的匿名函数绑定到对象。
为什么讲师(在第二个Person标签中)使我们在switchNameHandler中而不是在nameChangedHandler中使用bind方法?
App.js
import React, { Component } from 'react';
import './App.css';
import Person from './Person/Person'
class App extends Component {
state = {
persons: [
{ name: 'Peter', age: 20 },
{ name: 'Manu', age: 28 },
{ name: 'Stephanie', age: 24 }
],
otherState: 'some other value'
}
switchNameHandler = (newName) => {
//console.log('Was clicked!');
this.setState({
persons: [
{ name: newName, age: 20 },
{ name: 'Manu', age: 5 },
{ name: 'Stephanie', age: 30 }
]
})
}
nameChangedHandler = (event) => {
this.setState({
persons: [
{ name: 'Max', age: 20 },
{ name: event.target.value, age: 5 },
{ name: 'Stephanie', age: 30 }
]
})
}
render() {
return (
<div className="App">
<h1>Hi, I'm a React App</h1>
<button onClick={() => this.switchNameHandler('Maximilian!!!!!')}>Switch Name</button>
<Person
name={this.state.persons[0].name}
age={this.state.persons[0].age}></Person>
<Person
name={this.state.persons[1].name}
age={this.state.persons[1].age}
click={this.switchNameHandler.bind(this, 'Max!')}
changed={this.nameChangedHandler}>My hobbies: Racing</Person>
<Person
name={this.state.persons[2].name}
age={this.state.persons[2].age}></Person>
</div>
);
}
}
export default App;
Person.js
import React from 'react';
import './Person.css';
const person = (props) => {
return (
<div className="Person">
<p onClick={props.click}>I'm { props.name } and I am { props.age } years old!</p>
<p>{props.children}</p>
<input type="text" onChange={props.changed} value={props.name} />
</div>
)
};
export default person;
添加了React文档的: 我正在阅读反应文档(https://reactjs.org/docs/faq-functions.html),并且只有这一行:
如果需要访问处理程序中的父组件,则还需要将该函数绑定到组件实例(见下文)。
绑定渲染:(来自反应站点的代码)
class Foo extends Component {
handleClick() {
console.log('Click happened');
}
render() {
return <button onClick={this.handleClick.bind(this)}>Click Me</button>;
}
}
在我们的例子中,处理程序方法不在父组件中,而在同一组件中。在这种情况下,我也必须理解一些错误。
答案 0 :(得分:1)
如果您不绑定该函数,而仅将其作为参数传递,例如:
<Person
name={this.state.persons[1].name}
age={this.state.persons[1].age}
click={this.switchNameHandler}
changed={this.nameChangedHandler}>My hobbies: Racing</Person>
您将如上所述定义函数。当您尝试访问App
实例时,将得到未定义的消息:
switchNameHandler(newName){
console.log(this);// undefined
}
但是在您的情况下,switchNameHandler
是箭头功能。根据{{3}}文档
直到箭头函数,每个新函数都定义了自己的此值(根据函数的调用方式,在构造函数中为新对象,在严格模式函数调用中未定义,如果该函数被称为“对象方法”等)
但是即使知道这一点,为什么还要绑定函数呢?因为:
this
)'Max!'
)要回答第二个问题:nameChangedHandler
不需要绑定,因为它具有箭头功能,并且可以使用创建它的上下文。
答案 1 :(得分:0)
第一种情况(click={this.switchNameHandler.bind(this, 'Max!')}
)只是这样,您无需声明额外的函数即可将参数传递给function。最后,最终结果与上面的示例(onClick={() => this.switchNameHandler('Maximilian!!!!!')}
)相同,不同之处在于,在第一种情况下,它创建了一个箭头函数(which automatically binds this
)来调用带有自定义参数的方法第二个将参数与this
绑定在一起(创建一个新的函数对象)。
第二种情况(changed={this.nameChangedHandler}
),由于this
is automatically bound to arrow functions(并且此函数被声明为箭头函数),因此当作为prop传递时,您无需再次绑定它。
答案 2 :(得分:0)
有两种功能:
这种函数具有一个名为 this 的变量,该变量表示调用对象的上下文,可以隐式或显式传递。
const obj = {
test: function() {
console.log(this)
}
}
obj.test();
test();
const bindedTest = obj.test.bind(obj);
bindedTest();
在前面的示例中,我们使用 obj 的上下文调用了测试函数,因此它表示或等于obj(打印obj)。如果您在没有上下文的情况下调用该函数,则编译器将在窗口对象上下文(浏览器环境中的javascript全局对象)中搜索该函数。最后一次调用时,您首先将此词绑定到 obj 上下文,然后可以在任何地方使用它而不会丢失该绑定。
function test () {
console.log(this)
}
test();
在第二个示例中,您在没有上下文的情况下调用函数测试,而上下文未显式定义上下文,然后使用窗口对象上下文调用了函数。
箭头功能没有此。如果您在箭头函数中使用 this ,它将无法在其上下文中找到名为this的变量,因此它将在较高的上下文中搜索该变量,依此类推,直到为其找到一个值。
const obj = {
test: () => {
console.log(this)
}
}
obj.test();
在前面的示例中,我使用 obj 的上下文调用了测试函数。但是箭头函数没有this,因此它在上限范围(即全局对象(窗口))中搜索上下文。
就您而言,您不必在任何可能的地方绑定 this 直接使用它,因为您使用了箭头功能。