如何使用jquery live停止事件冒泡?

30

我正在尝试阻止一些事件,但是stopPropagation在“live”上不起作用,所以我不确定该怎么办。我在他们的网站上找到了这个。

  

Live事件不会像传统方式那样冒泡,并且无法使用stopPropagation或stopImmediatePropagation停止。例如,考虑两个click事件——一个绑定到“li”,另一个绑定到“li a”。如果发生单击事件,则将触发两个事件。这是因为当$(“li”).bind(“click”,fn);绑定时实际上是在说“每当单击事件发生在LI元素中或内部时,请触发此单击事件。” 要停止live事件的进一步处理,fn必须返回false

它说fn必须返回false,所以我尝试做的是

 $('.MoreAppointments').live('click', function(e) {
   alert("Hi");
   return false;
 });

但是那并没有起作用,所以我不确定如何使它返回false。

更新

这里有更多的信息。

我有一个表格单元格,并绑定了一个点击事件。

 $('#CalendarBody .DateBox').click(function(e)
    {
        AddApointment(this);
    });

所以AddApointment只是创建了一个UI对话框。

现在,实时代码(MoreAppointments)位于此表单元格中,并且基本上是一个锚点。因此,当我点击锚点时,它首先转到上面的代码(addApointment - 因此运行该事件),但不会启动我的对话框框,而是直接进入(MoreAppointment)事件并运行该代码。一旦该代码运行,它就会从“addApointment”启动对话框框。

更新2

这是一些HTML代码。我没有复制整个表格,因为它有些庞大,而且所有单元格都重复相同的数据。如果需要,我可以发布它。

 <td id="c_12012009" class="DateBox">
        <div class="DateLabel">
            1</div>
        <div class="appointmentContainer">
            <a class="appointments">Fkafkafk fakfka kf414<br />
            </a><a class="appointments">Fkafkafk fakfka kf414<br />
            </a><a class="appointments">Fkafkafk fakfka kf414<br />
            </a><a class="appointments">Fkafkafk fakfka kf414<br />
            </a><a class="appointments">Fkafkafk fakfka kf414<br />
            </a>
        </div>
        <div class="appointmentOverflowContainer">
            <div>
                <a class="MoreAppointments">+1 More</a></div>
        </div>
    </td>

1
你的标记语言长什么样? - cletus
7个回答

52

简单来说,你不能

问题

通常情况下,你可以阻止事件“向上传递”到外部元素的事件处理程序,因为内部元素的处理程序会先被调用。但是,jQuery的“live events”通过将所需事件的代理处理程序附加到文档元素上,并在事件冒泡到文档后调用适当的用户定义处理程序,在工作方式上有所不同。

Bubbling illustration
(来源:shog9.com)

这通常使得“live”绑定成为一种相当有效的绑定事件的方法,但它有两个主要的副作用:首先,任何附加到内部元素的事件处理程序都可以防止“live”事件触发其自身或其任何子元素;其次,“live”事件处理程序无法阻止直接附加到文档子元素上的任何事件处理程序触发。你可以停止进一步的处理,但你无法对已经发生的处理做任何事情...并且当你的live事件触发时,附加到子元素的处理程序已经被调用

解决方法

根据你发布的内容,最好的选择是同时对点击处理程序使用live绑定。完成后,你应该能够从.MoreAppointments处理程序中返回false,以防止调用.DateBox处理程序。

示例:

$('.MoreAppointments').live('click', function(e) 
{
  alert("Hi");
  return false; // prevent additional live handlers from firing
});

// use live binding to allow the above handler to preempt
$('#CalendarBody .DateBox').live('click', function(e)
{
   AddApointment(this);
});

哇,这讲得太有道理了。现在我必须选择最佳答案:你的答案解释了事件冒泡是如何工作的,并提供了解决方案;或者gnarf的解决方案,它不需要修改我的代码,也能正常工作,但在未来的情况下可能无法使用。 - chobo2
event.stopPropagation也提到了:http://api.jquery.com/event.stopPropagation/ - Kzqai

7
我使用了这样的代码,它对我有效:

$('#some-link').live('click', function(e) {
    alert("Link clicked 1");
    e.stopImmediatePropagation();
});

$('#some-link').live('click', function(e) {
    alert("Link clicked 2");    
});

所以,据我所知,现在JQuery支持使用live事件停止立即传播。


5
也许您可以检查点击事件是否发生在a元素上:
$('#CalendarBody .DateBox').click(function(e) {
  // if the event target is an <a> don't process:
  if ($(e.target).is('a')) return;

  AddApointment(this);
});

可能有效?


这似乎是有效的,只需进行更多测试。但是我想知道,如果单击事件是锚标签本身,是否会阻止其自身调用其余代码的情况是否存在。不过再说一遍,我对这个目标一无所知,所以这可能根本不是问题。 - chobo2
出于好奇,这行代码:if ($(this).is('a')) return; 是否与你的答案中的那行代码有所不同? - Hubro
@Codemonkey - 是的,event.target 总是指向实际被点击的对象,而 this 将会是 .DateBox - 你绑定事件的容器。 - gnarf

3
我正在使用这个:

if(event.target != this)return; // stop event bubbling for "live" event

$('#some-link').live('click', function(e) { if(e.target != this)return; })请注意:本文仅为程序相关内容翻译,不包含任何解释。 - RainChen

1

我使用

e.stopPropagation(); // to prevent event from bubbling up
e.preventDefault(); // then cancel the event (if it's cancelable)

1
我在某些情况下使用过这个。注意:并非总是适用,因此请根据您的需求进行评估:
html:
<a href="#" className="my-class-name">Click me</a>

在您的现场事件处理程序中的js:

if(e.target.className == 'my-class-name') {
    e.preventDefault();
    // do something you want to do...
}

这样,我的现场活动只有在单击特定元素类型/类名属性时才会“运行”。
这里的e.preventDefault()是为了防止我点击的链接将滚动位置移动到页面顶部。

0
Simply use **"on"** function to bind click event of child as well as parent element.

Example :  $("#content-container").on("click","a.childElement",function(e){
                   alert("child clicked");
                   e.stopPropagation() ; 
                }); 

                $("#content-container").on("click","div.parentElement",function(e){
                  alert("parent clicked");
                }); 
( where content-container is the outer div containing both parent as well as child elements. )

        Here only "child clicked" alert will occur.

    Thanks.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接