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

时间:2019-01-28 07:52:31

标签: reactjs event-handling event-propagation

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

比方说,该组件在其状态下具有一组item对象,ES6 map函数为每个项目呈现一个带有图标的按钮。单击一个按钮后,该按钮将被删除。

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

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

1-基于id或其他属性的event.stopPropagation()。来自(How to ONLY trigger parent click event when a child is clicked

<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;也可用于某些实现。

1 个答案:

答案 0 :(得分:0)

我不确定这些解决方案中的任何一个是否确实必要。要详细说明,请假设以下内容:

{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
   });
}

注意:无需阻止默认或传播,因为按钮(类型为按钮)的默认click事件不执行任何操作,也不需要停止传播,以防需要在更高级别附加其他事件处理程序。层次结构。