javascript - JQuery插件,多个实例同一页面;适用于元素类和唯一元素 ID;用 $.data 保护选项;公共(public)访问功能

标签 javascript jquery jquery-plugins boilerplate

我正在第一次编写 JQuery 插件 - 几乎已经完成 - 并试图找到最好的“样板”来满足以下需求。

这是我的问题:

See my JS Fiddle

我无法让插件通过类名来处理元素。

这有效:

var myPlugin = $('#single').myPlugin();   // Yes - it gets initialised
myPlugin.doAFunction(" Some Params ");    // Yes - public access func works

不起作用:

var myPluginFooClass = $('.foo').myPlugin(); // Yes, it gets initialised
myPlugin.doAFunction(" Some Params ");       // NO - now this falls over

这是我需要实现的目标:

  • 同一页面上有多个实例
  • 每个实例都有自己的变量,这些变量在部署时不会被其他实例覆盖(我使用的是 $.data)
  • 公共(public)访问函数仅影响该实例,而不影响其他实例!
  • 实例可以通过其 id (#myElement) 部署在单个元素上
  • 实例可以按类(.foo)部署在元素上 - 这是行不通的

这是我的 JQUERY 代码:

(function($){

$.fn.myPlugin = function(options) {
    // support multiple elements
    if (this.length > 1){
        this.each(function() { $(this).myPlugin(options) });
        return this;
    }

    // -- private variables --
    var $this = $(this);

    // default settings
    var defaults = { 
            initialText: 'I have been initialized'
        };
    // Merge defaults with setup options
    var options = $.extend({}, defaults, options);

    // Protect final options, placing inside jQuery element data 
    $this.data('myPlugSettings', options);

    // Shortcut var to access option data
    var settings = $this.data('myPlugSettings');

    // private methods
    var fooPrivate = function() {
        // do something private ...
    };

    // public methods        
    this.changeText = function(param) {
        $this.text(param);
    };

    // Constructor
    this.init = function() {
        $this.text( settings.initialText );
        // Return this for chainability?
        return this;
    };

    return this.init();
}
})(jQuery);



// globals

_ = {
    myPlugin: null,
    myPluginTwo: null,
    myPluginFoo: null
}


// Button Event handlers

$("#btnLoadPlugs").click(function(e) {
    _.myPlugin = $('#single').myPlugin({
        initialText: "Custom initial text" 
    });
    _.myPluginTwo = $('#anotherSingle').myPlugin();
    _.myPluginFoo  = $('.foo').myPlugin();
});

$("#btnGoSingle").click(function(e) {
    _.myPlugin.changeText(" Worked on single ID ");
});

$("#btnGoAnotherSingle").click(function(e) {
    _.myPluginTwo.changeText(" Worked again here ");
});

$("#btnGoFoo").click(function(e) {
    // THIS FALLS OVER ???????????
    _.myPluginFoo.changeText(" foos get this ");
});

My JS Fiddle这里让这个问题很容易理解。

最佳答案

TLDR

_.myPluginFoo 使用 changeText 方法释放对 jQuery 对象的引用。

// support multiple elements
if (this.length > 1){
    this.each(function() { $(this).myPlugin(options) });

    // Send the collection back.
    return this;
}

只是为了让它发挥作用

// This will work, but this is not exactly what you have intended.
_.myPluginFoo.each(function(key, value) {
    $(value).myPlugin().changeText('Hello');
});

为什么?

这是 Sizzle 选择器引擎的预期行为,$('#unique') 调用将返回带有单个 HTMLElement 的 jQuery Collection 实例,可通过$('#unique')[0]

通过将 $.fn.myPlugin 中的 $('#unique') 修改为 this,您将获得一个带有 changeThext 属性。

$('.foo').myPlugin() 的结果是 this.length > 1//true

通过调试以下代码,您将轻松注意到差异:

$("#btnLoadPlugs").click(function(e) {
    // ...

    console.log(_.myPluginTwo); // Single object.
    console.log(_.myPluginFoo); // A collection, without changeText method.
});
您使用的

$.data 保护不是很有效。

更好的方法

如果有意义的话,您还可以实现类似 $('.foo').myPlugin('changeText', 'new text') 的内容。

看看jQuery Boilerplate ,这是 jQuery 插件最好的事情之一。

关于javascript - JQuery插件,多个实例同一页面;适用于元素类和唯一元素 ID;用 $.data 保护选项;公共(public)访问功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31482718/

相关文章:

jquery - 向 jQuery 图像 map 插件添加反向突出显示?

javascript - 使用 xoxco 在搜索框的焦点上下拉 div

javascript - Cookie 仅在不使用 JSON.stringify 时设置

当通过 ajax 引入链接时,jquery colorbox 插件会中断

javascript - Jquery 插件可使用 PHP 中的值进行编辑

javascript - 如何使用所选选项禁用我的输入和内部内容

javascript - 如何实时查看在 Postgres 上执行的查询?

javascript - 为什么没有定义 ng-model?

javascript - 查询子文档 MongoDB Node.JS

jquery - 更改已加载页面中的 jQuery 单击处理程序 anchor