如何在单个页面上使用多个jQuery插件实例?

18

我正在编写一个简单的jQuery插件,但我在能够在页面上使用多个实例方面遇到了麻烦。

例如,这里有一个示例插件来说明我的问题:

(function($) {
  $.fn.samplePlugin = function(options) {
    if (typeof foo != 'undefined')
    {
      alert('Already defined!');
    } else {
      var foo = 'bar';
    }
  };
})(jQuery);

然后如果我这样做:

$(document).ready(function(){
  $('#myDiv').samplePlugin({}); // does nothing
  $('#myDiv2').samplePlugion({}); // alerts "Already defined!"
});

这显然是一个过于简化的例子,只为了表达重点。所以我的问题是,如何拥有两个独立的插件实例?我想在同一页上多个实例中使用它。

我猜问题的一部分可能与在全局范围内定义变量有关。那么如何将它们定义为该插件实例的唯一变量呢?

感谢您的指导!


example: https://gist.github.com/736705 - Toby
1
应该将 if (typeof foo == 'undefined') 改为 if (typeof foo != 'undefined') 吗? - Hailwood
9个回答

17

我也有同样的问题,但我找到了一个非常方便的解决方法,我会将其发布给可能遇到这个问题的人。

当您在插件内定义变量时,可以使用.data()来存储所有定义的变量。

像这样:

(function($) {
  $.fn.samplePlugin = function(options) {
    var base = this;
    this.foo // define foo

    // do stuff with foo and other variables

    // Add a reverse reference to the DOM object
    this.data("pluginname", base);

  };})(jQuery);

当你想要使用相同的foo变量时,你应该用以下代码来检索引用:

base = this.data("pluginname");
base.foo
希望能有所帮助 Logan

3

html:

<code class="resize1">resize1</code>
<code class="resize2">resize2</code>


<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script src="js/plugins.js"></script>
<script src="js/main.js"></script>
<script type="text/javascript">
       jQuery(document).ready(function($) {
           $('.resize1').ratiofix({message:'resize1'});
           $('.resize2').ratiofix({message:'resize2'});
       });
</script>

我找到了两个解决方案-第一个是jquery widget工厂 http://jqueryui.com/widget/ js代码:

$.widget("custom.ratiofix",{
    options:{
        message:"nothing"
    },
    _create:function (){
        var self=this;
        this.setListeners();
    },
    setListeners:function (){
        var self=this;
        $(window).on('resize',$.proxy(self.printMsg,self));
    },
    printMsg:function (){
         console.log(this.options.message);
    }
});

第二种方法(不使用小部件工厂):
(function ($){
var Ratiofix = {
  init: function(options, elem) {
    this.options = $.extend({},this.options,options);
    this.elem  = elem;
    this.$elem = $(elem);
    this.setListeners();
    return this;
  },
  options: {
    message: "No message"
  },
  printMsg: function(){
     console.log(this.options.message);
  },
  setListeners:function (){
    var self=this;
    this.$elem.on('click',function (){
         console.log(self.options.message);
    });
    $(window).on('resize',$.proxy(self.printMsg, self));
  }
};

  $.fn.ratiofix=function (options){
    this.init= function(options, elem) {
      this.options = $.extend({},this.options,options);
      this.elem  = elem;
      this.$elem = $(elem);

      return this;
  };

    if ( this.length ) {
      return this.each(function(){
        var ratiofix = Object.create(Ratiofix);
        ratiofix.init(options, this); 
        $.data(this, 'ratiofix', ratiofix);
      });
    }


  };
})(jQuery);

在这两种情况下,插件分别工作并具有自己的设置。在我的情况下 - 2个小部件侦听窗口的调整大小并将它们自己的选项消息打印到控制台。


2
我不确定您所说的插件有多个实例是什么意思。一个插件可以在任何元素上使用。
这条评论并没有为我澄清太多:
假设它是一个带有“颜色”参数的插件,并将对象转换为该颜色。在这种情况下,您需要多个实例,因为您正在处理多个页面元素变成多种颜色。
在这种情况下,您需要根据需要传入不同的颜色作为参数:
$('div#foo').makeColor('red');
$('div#bar').makeColor('blue');

每次调用插件时,它将使用您提供的任何参数。该插件不是需要实例的类。

2

我在这里提供我的解决方案:

(function ($){

    $.fn.plugin = function (options){
        var settings = $.extend({}, $.fn.plugin.defaults, options);
        settings.that = $(this);
        $.fn.plugin.init (settings);
    };

    $.fn.plugin.defaults = { objval: 'default' };

    $.fn.plugin.init = function (settings){
        settings.that.val (settings.objval);
    };

}( jQuery ));

$('#target1').plugin ({objval: 'not default'});
$('#target2').plugin ();

每次初始化对象时,设置变量都是独立的。

演示


1

不要写成这样

$("#divid1").samplePlugin();
$("#divid2").samplePlugin();

你可以这样做

$.plugin('samplePlugin1', samplePlugin);
$("#divid1").samplePlugin1();

$.plugin('samplePlugin2', samplePlugin);
$("#divid2").samplePlugin2();

你可以从这里获取更多细节 http://alexsexton.com/?p=51


1
直接回答您的问题,您可以使用jQuery.noconflict()来避免命名空间冲突,从而在页面上可能有多个实例。
var $j = jQuery.noConflict();
// Use jQuery via $j(...)
$j(document).ready(function() {
  // etc

检查这里

但我质疑你的设计。为什么要编写一个似乎不能在jQuery包装集上运行的插件?..插件应该被编写成假定它们正在操作存储在“this”中的jQuery数组。在这种情况下,可以在每个被操作的项目中存储任何状态...但也许您正在构建不同的东西?

请查看此页面


1

你需要使用this.foo而不是var foo,这样变量只与当前对象相关。


-1

这对我非常有效!我有特定的参数,想要在哪些页面/位置运行插件,并且通过使用简单的if语句成功实现了目标。希望这能帮助到某些人!

<!-- Begin JQuery Plugin Foo -->
<script src="js/foo_fun.js"></script>

<?php 
if(substr_count(strtolower($currentUrl),"member")>0)
{
?>
    <script>
    $(document).ready(function(){
        $('#vscroller').vscroller({newsfeed:'news_employee.xml', speed:1000,stay:2000,cache:false});
    });
    </script>
<?php
}
else
{
?>
    <script>
    $(document).ready(function(){
        $('#vscroller').vscroller({newsfeed:'news_company.xml', speed:1000,stay:2000,cache:false});
    });
    </script>
<?php
}
?>
<!-- End JQuery Foo--> 

这更像是一种黑客方式!如果您的页面上有许多地方需要这样做,它会使您的代码变得难以阅读和混乱。最好的选择是修复根本原因,即插件的多次初始化。 - Vishnu Narang

-4

我遇到了同样的问题:如何在一个表单上使用多个插件实例?通常的方法失败了,因为实际上,实例不是插件的实例:它是jQuery的实例。因此,如果定义了多个元素来由插件管理,则每个定义都会覆盖先前的参数。

必须从另一个角度来看待这个问题。

插件通常是为特定元素的特定事件而设计的。例如,单击按钮或鼠标悬停在元素上时。在我的情况下,我必须为城市字段使用自动完成插件,但我的表单有5个选项卡,总共有4个城市字段用于收集信息的4个不同部分。对于每个字段,参数都是特定的。

顺便说一下,我意识到我不需要始终启用插件:只需在适当的字段事件上启用即可。

所以我有了一个想法:为每个元素创建一个事件管理器。当事件发生时,我定义插件操作。以下代码更有效地解释了这个想法:假设您有3个div块,您的插件必须更改颜色,但具体颜色取决于哪个div受到影响。


$(document).ready(function(){
    // Wich elements are affected by the plugin
    var ids = ['myDiv1','myDiv2','myDiv3'];
    // foe each one :
    for (v in ids) 
    {
        //define from an event :
        $('#'+ ids[v]).focus(function()
        {
            // depending which id is active :
            var  aParams, idDiv = $(this).attr('id');
            // Choosing the right params
            switch(idDiv)
            {
                case 'myDiv1':
                    aParams = {'color': '#660000', 'background-color': '#0000ff'};
                    break;
                case 'myDiv2':
                    aParams = {'color': '#006600', 'background-color': '#ff00ff'};
                    break;
                case 'myDiv3':
                    aParams = {'color': '#000066', 'background-color': '#ff0000'};
                    break;
                default:
                    aParams = {'color': '#000000', 'background-color': '#ffffff'};
            };
            // Defining the plugin on the right element with the right params
            $(this).myPlugin(
            {
                colors: aParams
            });
        });
    }
});

这个很好用。

如果我的英语不太好,希望你能理解。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接