【问题标题】:How to invert Javascript element bubble order?如何反转Javascript元素气泡顺序?
【发布时间】:2019-12-18 18:21:17
【问题描述】:

我创建了一个自定义 Slider 组件,除了一个问题外,它可以完美运行。

如果它存在于模式中,则它的 mouseUp 事件会在其下方的所有事件(z-index-wise)之前在元素本身上触发。

这是因为要拥有一个漂亮的滑块,您需要将 mouseMovemouseUp 事件附加到文档而不是滑块本身,这样即使鼠标移动,您仍然可以移动拇指并捕获鼠标向上事件滑动拇指时离开滑块。

因此,我现在遇到了mouseUp 事件导致其下方元素的点击事件在滑块元素之前运行的问题。这会导致下面的按钮点击和模式关闭等问题(因为这些都是点击事件)。

一个潜在的解决方案是对所有可能被拦截的潜在事件处理程序添加检查(类似于if (thisModalOpened) { return false; } 对所有其他各种元素),但该解决方案似乎有点混乱。

有没有更好的方法?一种反转冒泡顺序的方法似乎可行,因为这样我就可以在 mouseUp 中为 Slider 组件调用 stopPropagation。但是,我不确定是否可以这样做,因为当前事件侦听器已在文档中注册,以便可以在元素本身之外检测到它。

一些代码sn-ps:

componentDidMount() {
  document.addEventListener("pointermove", this.onThumbMove, false);
  document.addEventListener("pointerup", this.onThumbUp, false);
}

onThumbDown = e => {
  this.setState({ dragging: true, startX: this.getX(e) });
}

onThumbMove = e => {
  if (this.state.dragging) {
    this.setState({ position: e.clientX });
  }
}

onThumbUp = e => {
  if (this.state.dragging) {
    let value = this.getValue();

    this.setState({ dragging: false }, () =>
      this.props.onSubmit(value);
    });
  }
}

<div onPointerDown={this.onThumbDown} ref={this.sliderRef}>
  <div>+</div>
</div>

编辑: 好的,我想我终于找到了问题所在(但我还不知道解决方案):所以,模态框通常(我的也是如此)有黑色背景您可以单击以轻松关闭模式。我可以将黑色背景作为模型内容的直接父级或父级的兄弟。

如果我将它作为直接父级,那么我必须在每个可能的子组件上调用stopPropagation / return false,以便单击它们不会导致单击向上传播并单击背景模态并使其关闭。所以我不希望它成为父母,因为那太麻烦了。

另一方面,如果我将它作为父级的兄弟,那么我不能在文档thumbUp 事件上调用stopPropagation,因为模态背景蒙版不是直接父级,因此它将被注册为尽管有stopPropagation 调用,但仍单击并关闭模式,因为它不是直接父级。

基本上,这两种方法都行不通。我不知道如何调和。

【问题讨论】:

  • 是的,你可以。请发布您当前的事件监听器和其他相关代码 sn-ps。
  • 当然可以。秒。
  • 您可以通过将true 作为第三个参数传递给event listner 来反转事件冒泡阶段,例如elem.addEventListener("mouseup", function () { console.log("mouseup event"); }, true);
  • @SarveshMahajan 我试过了,但似乎没有用。它已注册文档,因此将其设置为 true 只需先将其发送到文档(这已经在发生)。理想情况下,我可以将它注册到文档中,但让它从 Slider 组件开始。
  • 如果按钮是滑块的父级,而不是捕获,则默认冒泡正是您想要的。这里还有其他事情发生,特别是如果您在移动设备上进行测试。一起调用 stopPropagation 和 stopImmediatePropagation 以确保没有模拟事件被触发。而且由于 mouseup 和所有其他模拟事件都是在触摸事件之后触发的,因此您还需要在 touchmove 和 touchend 中调用它。

标签: javascript html reactjs modal-dialog event-bubbling


【解决方案1】:

正如 cmets 中提到的 @Sarvesh,您可以向事件侦听器添加第三个参数,但您需要使用 capture 选项从上到下而不是从下到上触发事件,而不是传递布尔值你想要这样:

document.addEventListener("pointerup", this.onThumbUp, { capture: true });

您现在可以在mouseUp 事件或任何其他事件中添加stopPropagation(),具体取决于您的需要。

【讨论】:

  • 这似乎不起作用。可能是移动问题(似乎只发生在移动设备上)?即使您提到了这些包含,点击事件仍会为其下方的元素激活。
  • 以上代码只能在桌面上运行还是不能在桌面和移动设备上运行?
  • 好吧,我从来没有在桌面上遇到过这个问题(尽管它可能只是因为桌面速度太快而并不明显)。它似乎只影响我的移动浏览器。不过,我已将其范围缩小到 onThumbUp 处理程序,因为如果我在第一行粘贴 return false; ,它可以解决问题(但显然会阻止滑块 thumbUp 工作。)
  • 等一下。让我试着弄清楚这一点。
  • 如果可能的话,您能否在这个样板反应沙箱中复制您的应用程序? CodePen Sandbox。我感觉现在可能是其他原因导致了问题,因为捕获选项可以根据需要反转冒泡。
猜你喜欢
  • 2010-12-13
  • 1970-01-01
  • 2013-10-27
  • 1970-01-01
  • 1970-01-01
  • 2011-12-18
  • 2020-06-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多