3

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

例如,给定以下 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);

这将从外部插件中的嵌套插件中检索选择元素,但我不希望它这样做。我也想在附加点击事件时做同样的事情。例如,下面的代码应该只在嵌套插件中附加点击事件,而不是在外部插件中。

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

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

4

5 回答 5

2

问题是,选择器是根据给定的上下文工作的。如果您告诉 jQuery 搜索一个 div,它将搜索该 div 中的所有内容以查找它要查找的内容。这就是 jQuery 的工作方式。

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

所以,这样做:

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

或者:

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

或者:

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

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

最后:

$('.select', element).not('[mySecondPlugin="true"]').on('click',  function(e) {
    ...
});
于 2013-05-20T19:02:28.770 回答
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;
        ...
    });
于 2013-05-20T18:37:51.237 回答
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');

见:小提琴

于 2013-05-20T23:19:25.900 回答
1

您可以使用jQuery .closest()从元素中查找第一次出现的选择器。因此,您可以使用#('.select').closest('.my-plugin').

使用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;
    }
});
于 2013-05-20T19:14:43.160 回答
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
});
于 2013-05-20T18:47:53.207 回答