React:事件传播的最佳实践(触发父事件,而不是子事件)



我一直在寻找在react组件中防止CHILD元素的事件和PARENT元素的触发事件的最佳方法。

假设组件有一个处于其状态的项对象数组,ES6map函数为每个项呈现一个带有图标的按钮。单击某个按钮时,该按钮将被删除。

{this.state.items.map(item => (
<button ...>...</button>
))}

到目前为止,我已经找到了3个解决方案。

1-基于id或其他属性的event.stopPropagation()。From(单击子项时如何仅触发父项单击事件)

<button id='parent' onClick={removeItem}>
<i id='child' className='fas fa-times-circle'></i>
</button>
removeItem(event) {
const target = event.target;
const id = target.id;
event.stopPropagation();
event.preventDefault();
if(event.target === 'parent') {
this.setState({
items: this.state.items.map(item => item.id != id)
});
}
}

2-将参数传递给事件处理程序,而不是事件本身

<button onClick={() => removeItem(item.id)}>
<i className='fas fa-times-circle'></i>
</button>
removeItem(id) {
this.setState({
items: this.state.items.map(item => item.id != id)
});
}

缺点:这是低效的,因为在每次渲染时都会重新创建对事件处理程序的新引用。

3-在父元素和所有子元素上重复自定义属性

<button itemid={item.id} onClick={removeItem}>
<i itemid={item.id} className='fas fa-times-circle'></i>
</button>
removeItem(event) {
const id = event.target.getAttribute('itemid');
this.setState({
items: this.state.items.map(item => item.id != id)
});
}

缺点:必须确保DOM树下的所有子元素都有itemid={item.id},这在这种情况下很困难(想想像polygon这样的svg元素)。

最好的方法是什么?我已经看到pointer-events: none;也可以与一些实现一起使用。

我不确定这些解决方案中的任何一个实际上都是必要的。详细假设如下:

{this.state.items.map(item => (
<button type="button" value={item.id} onClick={removeItem}>
<i className='fas fa-times-circle'></i>
</button>)
}

在事件处理程序中,您可以使用currentTarget,它模拟默认的event.currentTarget行为,特别是:

它总是指事件处理程序所附加的元素,而event.target则标识事件发生的元素。

您的事件处理程序可以是:

removeItem(event) {
const id = event.currentTarget.value;
this.setState({
items: this.state.items.filter(item => item.id != id) //assuming you intended to filter here
});
}

注意:没有必要阻止默认或传播,因为按钮(类型为button)的默认点击事件是不做任何事情的,而且在需要附加层次结构中更高级别的其他事件处理程序时,也不需要停止传播。

相关内容

  • 没有找到相关文章

最新更新