防止事件在 dom 树中冒泡

Prevent event from bubbling up the dom tree

我有一个卡片组件如下

<div
      onClick={e => {
        console.log("DEMAND CARD CLICKED");
        if (isSelectionActive) {
          setSelected();
        }
      }}
>  
      <DemandCardFooter
        demandId={id}
        totalBooked={totalBooked}
        totalDemand={totalDemand}
      />    
</div>

这就是 <DemandCardFooter/> 的样子:

<div className="vt-card-footer d-flex justify-content-between align-items-baseline px-3">
      <DemandSelector demandId={demandId} />
      <p className="lead font-weight-bold mb-0">
        <span className="text-success">{totalBooked}</span> / {totalDemand}{" "}
        <small className="text-muted font-weight-normal">Units.</small>
      </p>
</div>

最后是 <DemandSelector/> 的样子:

const DemandSelector = ({ demandId }) => {
  const [isChecked, setChecked] = useRowSelector({
    path: "demands",
    payload: { id: demandId }
  });
  return (
    <Checkbox
      checked={isChecked ? true : false}
      onClick={e => {
        console.log("CHECKBOX CLICKED");
        e.stopPropagation();
        e.nativeEvent.stopImmediatePropagation();
        setChecked();
      }}
    />
  );
};

我的问题是,当我点击复选框时,复选框的 onClick 和卡片的 onClick 都会被触发,有什么办法可以将回调限制在最低级别吗?

这不是事件冒泡的问题,问题是事件捕获阶段。

该事件不会随着您在代码中使用的 e.stopPropagation(); 冒泡。但是在父事件中并没有阻止事件捕获。

您可以通过在父事件中添加 e.stopPropagation(); 来阻止它。

<div
      onClick={e => {
         e.stopPropagation();
        console.log("DEMAND CARD CLICKED");
        if (isSelectionActive) {
          setSelected();
        }
      }}
    >
      <DemandCardFooter
        demandId={id}
        totalBooked={totalBooked}
        totalDemand={totalDemand}
      />
    </div>

一段时间后想通了。解决方案是将 stopPropogation() 放入包含 <DemandSelector/>

的 DOM 元素中

所以这段代码有效

 <div
      className="vt-card-footer d-flex justify-content-between align-items-baseline px-3"
      onClick={e => {
        e.stopPropagation();
      }}
    >
      <DemandSelector demandId={demandId} />
      <p className="lead font-weight-bold mb-0">
        <span className="text-success">{totalBooked}</span> / {totalDemand}{" "}
        <small className="text-muted font-weight-normal">Units.</small>
      </p>
    </div>

还有别忘了把它一直放下去

const DemandSelector = ({ demandId }) => {
  const [isChecked, setChecked] = useRowSelector({
    path: "demands",
    payload: { id: demandId }
  });

  return (
    <Checkbox
      checked={isChecked ? true : false}
      onClick={e => {
        e.stopPropagation();
        setChecked();
      }}
    />
  );
};