【问题标题】:How to have multiple instances of jQuery plugin on single page?如何在单个页面上有多个 jQuery 插件实例?
【发布时间】:2010-12-09 14:37:47
【问题描述】:

我正在编写一个简单的 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!"
});

这显然是一个过于简单化的例子。 所以我的问题是,我如何拥有插件的两个单独实例?我希望能够在同一页面上的多个实例中使用它。

我猜测问题的一部分可能在于在全局范围内定义变量。那我该如何定义它们对于该插件实例是唯一的呢?

感谢您的指导!

【问题讨论】:

  • 应该 if (typeof foo == 'undefined') 不是 if (typeof foo != 'undefined')
  • @Hailwood,是的,你是对的。谢谢!

标签: javascript jquery plugins jquery-plugins


【解决方案1】:

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

当您在插件中定义变量时,您可以使用 .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

希望对你有帮助

洛根

【讨论】:

    【解决方案2】:

    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>
    

    我找到了 2 个解决方案 - 第一个是 jquery 小部件工厂 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 个小部件监听窗口调整大小并打印到控制台自己的 options.message

    【讨论】:

      【解决方案3】:

      我不确定您所说的拥有多个插件实例是什么意思。插件可用于任何元素。

      这条评论对我来说并没有太多说明:

      所以说这是一个插件 一个“颜色”参数并转动 对象变成那个颜色。嗯,在那 如果您需要多个实例,例如 你处理的不止一页 元素会变成一种以上的颜色。

      在这种情况下,您可以根据需要传入不同颜色的参数:

      $('div#foo').makeColor('red');
      $('div#bar').makeColor('blue');
      

      每次调用插件时,它都会使用你给它的任何参数。该插件不是需要实例的类。

      【讨论】:

      • 谢谢内森,非常感谢!
      【解决方案4】:

      把我的解决方案扔在这里:

      (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 ();
      

      DEMO

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

      【讨论】:

        【解决方案5】:

        要直接回答您的问题,您可以使用 jQuery.noconflict() 来避免命名空间冲突,从而可能在页面上有多个实例化..

        var $j = jQuery.noConflict();
        // Use jQuery via $j(...)
        $j(document).ready(function() {
          // etc
        

        检查here

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

        请查看this page

        【讨论】:

          【解决方案6】:

          而不是写这个

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

          你可以这样做

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

          您可以从这里获得更多详细信息 http://alexsexton.com/?p=51

          【讨论】:

            【解决方案7】:

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

            【讨论】:

              【解决方案8】:

              这对我来说是一种享受!我对要运行插件的页面/位置有特定的参数,并且能够通过使用简单的 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--> 
              

              【讨论】:

              • 这更像是一个黑客!如果您的页面上有很多地方需要这样做,它会使您的代码不那么可读和混乱。最好的选择是解决根本原因,即插件的多次初始化。
              【解决方案9】:

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

              有必要换个角度看问题。

              插件通常用于对特定元素的特定事件做出反应。例如.. onclick 一个按钮,或者当鼠标悬停在元素上时。 就我而言,我必须为城市字段使用自动完成插件,但我的表单有 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
                          });
                      });
                  }
              });

              这很好用。

              对不起,如果我的英语不完美 - 我希望你能理解。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多