【问题标题】:Can I stop event propagation on certain function?我可以停止某些功能的事件传播吗?
【发布时间】:2013-12-06 01:45:47
【问题描述】:

我有一些 DIV,其他开发者将它们绑定一个点击事件名称fn_propagation

现在我想为它们添加一个新函数,名称为fn_stoppropagation

问题是当我在fn_stoppropagation 中调用e.stopPropagation() 时,它也会停止在fn_propagation 中的事件传播。

如何在fn_propagation 中保持事件传播,但在我添加的函数中停止传播? (我知道通过 ID 向每个 DIV 添加事件并停止使用 stopPropagation() 可以做到这一点,但我认为这不是一个好方法。)

小提琴:http://jsfiddle.net/android/3GurB/2/

HTML:

<div id='div1'>
    <div id='div2'>
        <div id='div3'>
            Click Me
        </div>
    </div>
</div>

JS:

$('div').click(fn_propagation)      // Other developer add this event
        .click(fn_stoppropagation); // What I going to add.

// I want to keep propagation of this function 
function fn_propagation(){
    alert('propagation '+$(this).attr('id')+' called');
    $(this).toggleClass('green');
}

// But stop propagation of this function
function fn_stoppropagation(e){
    alert('stoppropagation '+$(this).attr('id')+' called');
    e.stopPropagation();
}

Click Me 被点击时,期望输出:

   propagation div3 called     // called
   stoppropagation div3 called // called
   propagation div2 called     // expected, but NOT called, 
   propagation div1 called     // expected, but NOT called, 

谢谢。

【问题讨论】:

  • 这正是我所期望的。为什么你认为它是错误的(除了我错了)
  • 使用'div' 作为选择器的糟糕示例...肯定选择器比这更具体?
  • 函数不冒泡,事件冒泡。从任何处理程序停止事件都会停止它。不能同时冒泡和不冒泡。
  • @charlietfl:我认为 OP 这样做是为了将处理程序分配给所有嵌套元素以进行说明。

标签: javascript jquery stoppropagation


【解决方案1】:

传播发生在 DOM 中,它只能为整个元素打开或关闭,而不是特定的事件处理程序。

我的建议:将当前元素与click target进行比较:

function fn_stoppropagation(e){
  if (this===e.target) {
    // the following will only run for the target, not its ancestors
    alert('stoppropagation '+$(this).attr('id')+' called');
  }
}

【讨论】:

  • 谢谢,这就是我想要的
  • @andyf:你确定你最深的元素与处理程序永远不会有另一个嵌套元素吗?就像在您的示例中添加嵌套的 &lt;span&gt; 一样?如果是这样,这将不起作用。
  • @Blue Skies:这是个问题...也许我可以使用 $('div *') 让它工作?
  • @BlueSkies 好点。在这种情况下,也许使用 $(e.target).closest("div")[0] 代替?
  • @andyf:您将把处理程序分配给从所有 div 继承的所有元素。只要您最终不在乎单击了哪个元素,它就可能会起作用。
【解决方案2】:

您拥有的是嵌套的 div,每次处理点击。由于它们是嵌套的,因此事件会冒泡 - 从最里面的 div 开始。所以你不能stopPropogation 期望它会传播到泡沫中。 stopPropogation 就是为此而生的——停止将事件冒泡给其他处理程序。

【讨论】:

    【解决方案3】:

    您的方法是错误的,因为事件传播独立于事件处理程序,因此您不能为某些人停止事件,也不能为其他人停止。

    您可能认为只为某些人停止它是有意义的,但那是因为您的情况是一个特殊的情况:目标及其祖先具有相同的处理程序。

    但在更一般的情况下,冒泡事件会触发每个元素可能不同的事件处理程序,因此仅对某些处理程序停止事件传播没有意义。

    然后,正确的方法是修改事件处理程序而不是事件。 例如:

    var stopped = false;
    function fn_stoppropagation(e){
        if(stopped !== (stopped=true)){
            /* Code here */
        }
    }
    

    Demo

    【讨论】:

    • 对我来说似乎是一个很好的解决方案。不过可能需要一种重置方法。
    • 这有什么帮助?因为 fn_stoppropagation 永远不会被多次调用。
    • 你能提供你的演示吗?
    • @VikramRao:当然是......当它冒泡到分配了相同处理程序的下一个元素时。
    • @andyf 对不起,我忘了添加链接
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-05
    相关资源
    最近更新 更多