处理嵌套在组件中的组件的JS事件的最佳方法?

问题描述 投票:0回答:1

例如,选项卡组件中的一个选项卡组件。我目前正在开发Titon Toolkit(https://github.com/titon/toolkit)的下一个主要版本2.0,我想尽可能轻松地支持这种情况。当前在1.0中,无法嵌套。

Toolkit中的组件使用事件委托来绑定组件内的交互。事件绑定到组件包装器(顶级父组件),并使用类委托给其中的所有子组件(在2.0中,它们使用数据属性进行CSS / JS解耦)。现在您可以看到问题了。如果事件绑定到父组件,则它们也将绑定到任何嵌套组件,并且它们共享相同的类名(或数据属性)。此外,绑定到孩子的任何事件现在都将触发2个事件,哦,不!

问题的简要示例。

<div class="tabs" id="tabs-1" data-tab>
    <ul class="tab-nav" data-tab-nav>
        <li><a href="">1</a></li>
        <li><a href="">2</a></li>
        <li><a href="">3</a></li>
    </ul>

    <section class="tab-section" data-tab-section></section>
    <section class="tab-section" data-tab-section></section>
    <section class="tab-section" data-tab-section>

        <div class="tabs" id="tabs-2" data-tab>
            <ul class="tab-nav" data-tab-nav>
                <li><a href="">1</a></li>
                <li><a href="">2</a></li>
                <li><a href="">3</a></li>
            </ul>

            <section class="tab-section" data-tab-section></section>
            <section class="tab-section" data-tab-section></section>
            <section class="tab-section" data-tab-section></section>
        </div>

    </section>
</div>

事件绑定成这样:

$('#tabs-1').on('click', '[data-tab-nav] a', showSection); // Also being bound to #tabs-2 elements
$('#tabs-2').on('click', '[data-tab-nav] a', showSection);

这是我所处的困境。解决这个问题的最简单或更好的是,最不容易出错的方法是什么?这些是我目前仅有的解决方案。

  1. 对嵌套元素绑定stopPropagation()。这不是一个很好的解决方案,因为可能需要冒泡,并且也需要由开发人员处理。
  2. 将数据属性与值一起使用。例如,使用数据属性[data-tab="foo"]初始化选项卡组件将仅将事件绑定到具有相同数据属性值的元素,例如[data-tab-nav="foo"] a。因此,如果父级为foo,子级为bar,则所有内容都将正确绑定。将需要更多的标记,但没有缺点。
  3. 在绑定到并且可以自定义的父级和子级中使用自定义类。

有什么想法?有什么建议吗?

javascript jquery components jquery-events event-bubbling
1个回答
0
投票

这是我想到的最简单的方法(演示:http://jsfiddle.net/brdgc05d/3/:]

var tabClasses = ['#tabs-1', '#tabs-2'];

$.each(tabClasses, function(index, tabClass) {
   $(tabClass).on('click', '[data-tab-nav] a', function(e) {
       e.preventDefault();
       if ( $(e.delegateTarget).parents('[data-tab]').length ) { // must use delegateTarget, otherwise $(e.delegateTarget) would be the <a> element they clicked rather than $('#tabs-n')
           // is a child, so you could abort the event here
           alert(tabClass + ' clicked and IS a child');
       } else {
           // is not a child
           alert(tabClass + ' clicked and is NOT a child');
       }
    });
});
© www.soinside.com 2019 - 2024. All rights reserved.