Javascript 委托时,选择器中只有直接子级

Javascript 委托时,选择器中只有直接子级,javascript,javascript-events,jquery,Javascript,Javascript Events,Jquery,您好,我正在尝试使用.on将事件绑定到元素的子元素 dom看起来像这样 table>tbody>tr+>td>table>tbody>tr+ 到目前为止我已经试过了 table.find(“>tbody”)。在(“dbclick”,“tr”,listenerFunction) table.on(“dbclick”,“tbody>tr”,listenerFunction) 如果使用table.on(“dbclick”,“tr”,listenerFunction)与嵌套表冲突,导致双触发器等,因

您好,我正在尝试使用
.on
将事件绑定到元素的子元素

dom看起来像这样

table>tbody>tr+>td>table>tbody>tr+

到目前为止我已经试过了

  • table.find(“>tbody”)。在(“dbclick”,“tr”,listenerFunction)
  • table.on(“dbclick”,“tbody>tr”,listenerFunction)
如果使用
table.on(“dbclick”,“tr”,listenerFunction)
与嵌套表冲突,导致双触发器等,因为两个表都有此侦听器

任何最受欢迎的想法

编辑:HTML

<table>
  <tbody>
   <tr><!--Selectable row, adds the row after with sub table --></tr>
    <tr>
      <td>
        <table>
          <tbody>
            <tr></tr>
          </tbody>
        </table>
      </td>
    </tr>
  </tbody>
</table>

在侦听器函数中,使用
event.stopPropagation
停止事件冒泡返回到父级
tr

function listenerFunc(e) {
    e.stopPropagation();

    // Do your thing...
}
如果第一个
本身未嵌套,则可以提供一个选择器,该选择器仅匹配不是其他
元素后代的
元素:

table.on("dbclick", "tr:not(tr tr)", listenerFunction);

我的建议是在子表中添加
id
class
。这将确保它不会与页面上的任何其他元素或将来发生的任何修改冲突。假设您将一个类
嵌套表
添加到子表中。代码如下所示:

$('table.nested-table tr').dblclick(listenerFunc)
正如您所指出的,您引用了表,这应该可以:

表.on('dblclick','tr',listenerFunc)

试一试


演示:

事实证明,这部分是我忘记了防止事件冒泡,部分是jquery 1.7中的一个bug/缺失特性

在两个jsfiddle中使用相同的代码

在jQuery 1.7.2中,将“>tr”作为选择器传递到
.on
不起作用,我不知道这是一个bug还是1.7.2中没有实现的东西,但是
.on
方法是在1.7中添加的

下面的代码再现了该错误。我已经在Mountain Lion上运行的Chrome和Windows7上运行的Chrome上进行了测试

HMTL:


请发布你的HTML…我的HTML看起来像上面,但我会发布它。你发布的HTML是无效的。
td
元素不能直接包含
tr
元素。或者这只是一个复制和过去的错误?@FelixKling这不是实际的代码,只是一个示例。在我的示例中,表变量已经唯一地引用了表。另外,从文章中可能还不清楚,但是添加侦听器时,行不存在。您的代码不工作的原因是由于“>tr”,这意味着目标元素的直接子元素。原因是由于jQuery 1.7.2/3中的错误,请参阅我的答案。我同意您在jQuery on direct后代(>)中关于错误的陈述。然而,我上面给出的解决方案是有效的。我修改了你的小提琴。See可能会工作,但两个表运行相同的代码,因为这些表可以动态创建,因此我不能考虑表的深度。我认为这是唯一可行的解决方案。由于元素是嵌套的,因此无论选择器是如何构造的,单击内部
tr
总是会触发“父级”
tr
元素的处理程序。@HugoT:cause events bubble。即使
tbody.on(“dbclick”,“tr”,listenerFunction)
只侦听顶级
tr
上的事件,嵌套
tr
触发的事件将冒泡并触发处理程序。@HugoT后者不起作用,因为引发了两个单独的事件。单击
tr
,它是子
表的直接子级,然后单击
tr
,它是父
表的直接子级。
@Hugo:正如我所说,它不能像那样工作的原因是事件在DOM树上冒泡。单击子体将触发父事件处理程序。
>tr
仅用于事件委派,基本上意味着“如果在
tr
子级中触发了单击事件”。由于
tr
是嵌套的,因此内部
tr
将触发外部
tr
的处理程序。请参见此处的
>tr
tr
之间的区别:。单击“外部”和“内部”
tr
将触发处理程序两次,
>tr
仅触发一次。@Hugo:也许这些链接有帮助:。
var table = $('#tbl')
table.on("click", "> tbody > tr", listenerFunction);

function listenerFunction(e){
    if(!$(this).children().filter($(e.target).closest('td')).length){
        return;
    }
    console.log('direc tr')
}
<table id="outer">
    <tbody>
        <tr id="outer-row">
            <td>Hello</td>
            <td>World</td>
        </tr>
        <tr id="outer-row-1">
            <td>
                <table id="inner">
                    <tbody>
                        <tr id="inner-row">
                            <td>nested
                            </td>
                         </tr>
                    </tbody>
                </table>
            </td>
        </tr>
    </tbody>
</table>
$(function() {
    var handle = function(e) {
        console.dir(this.id);
    };


    $("#outer").children("tbody").on("dblclick", ">tr", handle);
    $("#inner").children("tbody").on("dblclick", ">tr", handle);
});