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

时间:2014-09-30 23:52:52

标签: javascript jquery javascript-events components event-bubbling

例如,制表符组件中的制表符组件。我目前正在研究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"]初始化tabs组件只会将事件绑定到具有相同数据属性值的元素,例如[data-tab-nav="foo"] a。因此,如果父级为foo且子级为bar,则所有内容都将正确绑定。需要更多标记但没有缺点。
  3. 在绑定的父级和子级中使用自定义类,并且可以自定义。
  4. 思考?建议?感谢您的投入!

1 个答案:

答案 0 :(得分: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');
       }
    });
});
相关问题