我有一个反应组件,它使用单独的 OnClick 呈现列表项。
为了找出单击了哪个项目,处理程序接受一个参数。处理程序确实被调用 - 但无论单击哪个项目 - 控制台始终记录 item3 (就像单击了 item3 一样)。我在这里做错了什么?
class Item {
constructor(props) {
super(props);
this.onItemClickHandler = this.onItemClickHandler.bind(this)
}
onItemClickHandler (itemName) {
console.log("Clicked " + itemName)
}
render() {
this.items = ["item1", "item2", "item3"]
var lis = []
for (var liName in this.items) {
var liName2 = this.items[liName]
console.log("Adding " + this.items[liName])
lis.push(<li className="item-ListItem" key={this.items[liName]} onClick={() => this.onItemClickHandler(this.items[liName])}><span><a href="#">{this.items[liName]}</a></span></li>)
}
return (
<div className="item">
<label className="item-Header"><u>items</u></label>
<ul className="item-List">
{lis}
</ul>
</div>
);
}
这行:
onClick={() => this.onItemClickHandler(this.items[liName])}>
似乎是正确的。
问题是你没有捕捉到价值this.items[liName]
正确,因为当你到达第三个项目迭代时onClick
处理程序的值始终为this.items[liName]
设置为第三项。
解决方案是使用闭包正确捕获值,我编辑了您的代码并在此链接中创建了一个完整的工作示例
https://codesandbox.io/s/3xrp6k9yvp https://codesandbox.io/s/3xrp6k9yvp
下面还写了示例代码和解决方案
class App extends Component {
constructor(props) {
super(props);
this.onItemClickHandler = this.onItemClickHandler.bind(this);
}
onItemClickHandler(itemName) {
console.log("Clicked " + itemName);
}
render() {
this.items = ["item1", "item2", "item3"];
var lis = [];
for (var liName in this.items) {
var liName2 = this.items[liName];
console.log("Adding " + this.items[liName]);
//the clickHandler function here is the solution we created a function that get executed immediately each iteration and return a new function that has the correct value of `this.items[liName]` saved
var clickHandler = (item => {
return event => {
this.onItemClickHandler(item);
};
})(this.items[liName]);
lis.push(
<li
className="item-ListItem"
key={this.items[liName]}
onClick={clickHandler} // here we use the clickHandler function directly
>
<span>
<a href="#">{this.items[liName]}</a>
</span>
</li>
);
}
return (
<div className="item">
<label className="item-Header">
<u>items</u>
</label>
<ul className="item-List">{lis}</ul>
</div>
);
}
}
有关闭包的更多信息和示例,请查看此link https://github.com/amrlabib/javascript-essentials-how-why/blob/master/closure.md
Edit我们可以用let
在 ES6 中代替var
正如 @ArchNoob 所提到的,在我们的 for 循环中,因为使用let
将使liName
块作用域
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)