【问题标题】:Not sure where to use stopPropagation or preventDefault (or both) in this situation?不确定在这种情况下在哪里使用 stopPropagation 或 preventDefault(或两者)?
【发布时间】:2014-07-22 00:51:35
【问题描述】:

我有一个具有相当大的点击区域的锚点,其中还有一个选择下拉菜单,当单击选择时不应激活链接。我知道这可能不是“规范”,但我需要锚提供的功能(即 cmd-click 在新的浏览器选项卡中打开)并且不知道任何其他方式。

这是我所拥有的大致轮廓:

<a id="anchor" href="http://google.com" onclick="anchor(event)">
  <div id="div">
    <select id="select" onclick="select(event)">
      <option>Option A</option>
      <option>Option B</option>
      <option>Option C</option>
     </select>
  </div>
</a>

这是一个通常显示我正在尝试做的事情的小提琴:

http://jsfiddle.net/C3g6b/

但是,这不是一个很好的测试方法,因为 fiddle 不允许您跟踪链接,因此您永远不会真正知道发生了什么。我建议将此独立粘贴到浏览器中:

http://pastebin.com/cvSBFAM8

问题是,每当我单击选择时,它都会跟随锚点。我已经尝试在(现在是裸露的)函数中使用各种 stopPropagation 和 preventDefault ,但我什么也做不了。显然,当您不单击下拉菜单时,我仍然希望锚点起作用。

更糟糕的是,我可以让它主要在 chrome 中工作,但它在 Firefox 中不起作用(还没有真正测试过 IE 或其他)。似乎在第一次单击时会显示选择,但随后我使用的 preventDefault() 会破坏其他所有内容。

任何建议,即使与我的建议有很大不同但实现了相同的目标,我们将不胜感激。谢谢!

【问题讨论】:

标签: javascript html css dom


【解决方案1】:

你能否将&lt;select&gt;移到DOM中&lt;a&gt;之外,并使用CSS使它们重叠?您可以将它们都放在一个具有相对定位的盒子中,以使它们分组;这是一个演示:http://jsfiddle.net/C3g6b/4/


(原答案:仅适用于 Chrome)

您的处理程序没有被调用,因为您将 JSFiddle 设置为调用 JavaScript onload,这意味着所有内容都包装在一个函数中,这意味着函数声明的范围仅限于该函数,并且在全局范围内不可用。通过将 JSFiddle 设置为不包装 JavaScript 或创建如下函数来解决此问题:

window.select = function () {

一旦你这样做了,e.preventDefault() 应该这样做。

我应该注意,如果您使用推荐的方法添加事件侦听器addEventListener,则不会发生此问题。

【讨论】:

  • 你调整了jsFiddle的例子并自己尝试了吗?我做了,但仍然没有用,但也许我做错了什么。
  • 但是现在你阻止了选择元素改变它的值。我增加了宽度以使其更清晰:jsfiddle.net/C3g6b/2.
  • @twberger:很抱歉造成误会,处理程序被称为很好。我的意思是锚的 href 不会被遵循,因为 jsfiddle 不允许它。由于小提琴不允许它,您甚至无法看到问题。
  • @FelixKling:是的!这显示了我在 chrome 和 firefox 之间提到的问题。您的示例在 chrome 中运行良好,但在 Firefox 中没有。如何让它在 Firefox 中工作?
  • @rjcarr 是的,但这只是另一个 JSFiddle 工件,与问题无关。当我在测试时,我正在查看控制台是否存在 x 域错误,以判断它何时尝试跟踪链接。此外,具体行为取决于浏览器 - Chrome 会触发错误,Firefox 会加载空白页面。
【解决方案2】:

您可以使用属性e.target 来确定事件的来源。所以在anchor 事件处理程序中,只需检查e.targetselect 元素,如果匹配,您就知道用户点击了选择框。那时您可以从处理程序返回 false 并阻止浏览器打开链接。

<a id="anchor" href="http://google.com" onclick="return anchor(event)">
  <div id="div">
    <select id="select" onclick="select(event)">
      <option>Option A</option>
      <option>Option B</option>
      <option>Option C</option>
    </select>
  </div>
</a>
function anchor(e) {
  if (e.target == document.getElementById('select')) {
    console.log('Preventing link click');
    return false;
  }
  console.log('Allowing link click');
  return true;
}

function select(e) {
}

一个例子是http://jsfiddle.net/mks_ios/8XXrt/。如果您打开 Chrome 或 Firefox Web 控制台,您将看到日志消息。

我在这里使用内联事件注册来不偏离您的示例,但我建议远离它们并在 JavaScript 中注册所有事件。一方面,您不必在onclick 中显式传递eventreturn 处理程序的返回值。 (请参阅http://www.quirksmode.org/js/events_early.html 上的“不要使用它”。)

此外,在这个问题中,它确实有助于理解事件模型以及事件如何在元素之间传播。这篇文章很好解释:http://www.quirksmode.org/js/events_order.html.

【讨论】:

    猜你喜欢
    • 2017-06-14
    • 1970-01-01
    • 2021-02-04
    • 1970-01-01
    • 2017-12-17
    • 2016-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多