jQuery嵌套插件选择器问题

时间:2013-05-16 13:19:53

标签: javascript jquery jquery-selectors

我希望能够将一个插件嵌套在另一个插件中。但是我的选择器过于激进并且不断检索嵌套插件的元素。

例如,给出以下HTML:

<div class="my-plugin">
    ...
    <div class="my-plugin">
        ...
        <button class="select">Select</button>
    </div>
</div>

使用以下代码创建插件:

$(function() {
    $('.my-plugin').myPlugin();
});

当我说下面的内容(在我的插件中)时:

// element is the element the plugin is attached to
$('.select', element);

这将从外部插件中的嵌套插件中检索select元素,但我不喜欢它。我还想在附加点击事件时也这样做。例如,以下代码应该只在嵌套插件中附加click事件,而不是在外部插件中。

element.on('click', '.select', function(e) {
    ...
});

我希望我已经清楚地解释了这一点。如果有人能告诉我如何改进我的选择器来处理这个问题,我将不胜感激。感谢

5 个答案:

答案 0 :(得分:2)

问题是,选择者会根据他们给出的上下文进行操作。如果你告诉jQuery搜索一个div,它将搜索该div中的所有东西以寻找它正在寻找的东西。这就是jQuery的工作原理。

如果要排除内部插件,请为其指定ID并使用.not()将其排除。或者你也可以给它一个类或data- *属性。我们只需要将其标记为“不包括”。

所以,这样做:

$('.select', element).not('#mySecondPlugin');

或:

$('.select', element).not('.mySecondPlugin');

或:

$('.select', element).not('[mySecondPlugin="true"]');

此选择器将选择外部元素中的所有内容,除了内部元素及其内容。

最后:

$('.select', element).not('[mySecondPlugin="true"]').on('click',  function(e) {
    ...
});

答案 1 :(得分:1)

这是我推荐的方法。

初始化时:

    $(element).addClass('my-plugin');
    var $selects = $(element).find('select')
                   .not( $(element).find('.my-plugin select') );

您必须确保插件中的所有功能都可以访问element$selects变量。

关于on()的说明,这是我的建议:

    element.on('click', '.select', function(){
        // see if the closest .my-plugin is the matching element, and not 
        // a child plugin
        if ( ! $(this).closest('.my-plugin').is( element ) )
            return;
        ...
    });

答案 2 :(得分:1)

您可以使用jQuery .closest()从元素中查找第一个选择器。因此,您可以使用#('.select').closest('.my-plugin')定位嵌套div。

使用jQuery .filter()

var myPlugin = this;//or whatever is representing your plugin jQuery object.
var selectsYouWant = $('.my-plugin .select').filter(function(index){
    if(this.closest('.my-plugin') === myPlugin) {
        return true;
    } else {
        return false;
    }
});

答案 3 :(得分:1)

您需要了解事件。单击元素时,事件会冒出DOM树。您需要停止传播,以便它不会到达外部插件处理程序。根据逻辑,您可能还需要阻止默认操作:

element.on('click', '.select', function(e) {
    e.stopPropagation();
    e.preventDefault();
    // ...
});

另外,不确定插件内部的逻辑是什么,但你可以过滤掉内部项目:

var button = $('.my-plugin').find('.select').not('.my-plugin .my-plugin *');
button.css('color', 'red');

请参阅:FIDDLE

答案 4 :(得分:0)

尝试在第一个插件之外启动:

例如:

<div class="plugin-wrapper">
    <div class="my-plugin">
        ...
        <button class="select">Select</button> //We want this one
        <div class="my-plugin">
            ...
            <button class="select">Select</button> //Without this one
        </div>
    </div>
</div>

然后,您就可以使用类似$('.plugin-wrapper > .my-plugin > .select')的内容,只有.select才会获得第一个$('.plugin-wrapper > .my-plugin > .select').on('click', function () { //Your code here }); 。我相信你正在努力实现的目标

对于onclick

{{1}}