对项目不起作用的 OnClick 做出反应

2024-01-09

我有一个反应组件,它使用单独的 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(使用前将#替换为@)

对项目不起作用的 OnClick 做出反应 的相关文章

随机推荐