React中为数组元素添加自定义onClick事件监听报错求助
解决Uncaught TypeError: item[i].addEventListener is not a function问题
嘿,我来帮你搞定这个问题!你遇到的错误根源其实很直白:你定义的item数组里装的都是普通字符串("A"、"B"这类),而addEventListener是DOM元素专属的方法,字符串根本没有这个API,所以浏览器才会报错说它不是函数。
另外还有个小细节要注意:componentWillMount这个生命周期钩子在React 17及以后已经被废弃了,而且就算你用它,此时组件还没渲染到页面上,也拿不到任何DOM元素,完全没必要在这里做事件绑定。
下面给你两种符合React设计理念的正确实现方式:
方式一:React声明式事件绑定(推荐)
直接在JSX里通过onClick属性绑定事件,这是React最推荐的写法,不需要手动操作DOM,代码更简洁易维护:
// 建议变量名改成items,更贴合数组的语义 var items = ["A", "B", "C", "D"]; export default class Test extends React.Component { handleClick(index) { console.log("check", index); } render() { return ( <div> {/* 遍历数组渲染成可点击的按钮元素 */} {items.map((itemText, index) => ( <button key={index} onClick={() => this.handleClick(index)} > {itemText} </button> ))} </div> ); } }
这里我们把每个字符串渲染成<button>元素,通过onClick直接把点击事件和处理函数绑定,点击每个按钮时就能正确打印对应的索引了。
方式二:手动操作DOM(不推荐)
如果你非要手动绑定DOM事件(不建议这么做,React的事件系统已经足够好用),那也要等到组件渲染完成后,在componentDidMount里获取DOM元素再绑定:
var items = ["A", "B", "C", "D"]; export default class Test extends React.Component { componentDidMount() { // 组件渲染完成后,获取所有带.item类的DOM元素 const domItems = document.querySelectorAll(".item"); domItems.forEach((domItem, index) => { domItem.addEventListener("click", () => this.handleClick(index)); }); } handleClick(index) { console.log("check", index); } render() { return ( <div> {items.map((itemText, index) => ( <div key={index} className="item" > {itemText} </div> ))} </div> ); } }
但再次强调,这种方式不如第一种优雅,React的声明式写法更符合框架的设计思路,也更便于后续维护。
内容的提问来源于stack exchange,提问作者Vikas Singh
相关产品推荐
相关产品推荐

