JQuery 样板插件对新实例使用相同的内部变量

JQuery Boilerplate plugin uses the same internal variables for new instance

我基于样板模板创建了一个简单的 JQuery 插件。除了一个问题外,它工作得很好。当我将我的插件应用于第二个 <div> 时,第一个停止工作。此外,所有 div 都具有我在创建新实例时生成的相同唯一 ID。如何重组现有代码以封装变量并使其正常工作? 下面的代码是我的插件:

;(function($) {

    var pluginName = "Pulsar",
        dataKey = "plugin_" + pluginName,
        defaults = {
            key : "color",
            from: "#000",
            to: "#fff",         
            duration: 5         
        };

    var self = null;
    var interval = null;    
    var flag = false;
    var uniqueID = uniqueId();

    //PRIVATE FUNCTIONS
    function Plugin( element, options ) {
        this.element = element;
        this.options = $.extend( {}, defaults, options) ;
        this._defaults = defaults;
        this._name = pluginName;

        this.init();        
    }

    function uniqueId() {
      return 'id-' + Math.random().toString(36).substr(2, 16);
    };      

    function Init(key, from, to, duration){
        $(self.element).css({ 
            WebkitTransition : 'all ease '+duration+'s',
            MozTransition    : 'all ease '+duration+'s',
            MsTransition     : 'all ease '+duration+'s',
            OTransition      : 'all ease '+duration+'s',
            transition       : 'all ease '+duration+'s' 
        });
        $(self.element).text($(self.element).text()+' '+uniqueID);  

        var state1, state2; 

        state1 = '{ "'+key+'" : "'+from+'"}';
        state2 = '{ "'+key+'" : "'+to+'"}';

        var state1JSON = JSON.parse(state1);
        var state2JSON = JSON.parse(state2);

        $(self.element).css(state1JSON);

        clearInterval(interval);
        interval = setInterval(function(){
            if(!flag){
                $(self.element).css(state2JSON);
                flag=true;                  
            }
            else{
                $(self.element).css(state1JSON);
                flag=false;             
            }               
        }, duration * 1000);
    }

    //PUBLIC FUNCTIONS
    Plugin.prototype = {
        init: function(){
            self = this;
            $(self.element).attr("pluginID", uniqueID);         
            Init(this.options.key, this.options.from, this.options.to, this.options.duration);
        },
        update: function(key, from, to, duration){          
            Init(key, from, to, duration);          
        },
        getID: function(){
            return uniqueID;
        }
    };

    $.fn[pluginName] = function ( options ) {
        var plugin = this.data(dataKey);

        // has plugin instantiated ?
        if (plugin instanceof Plugin) {
            // if have options arguments, call plugin.init() again
            if (typeof options !== 'undefined') {
                plugin.init(options);
            }
        } else {
            plugin = new Plugin(this, options);
            this.data(dataKey, plugin);
        }

        return plugin;
    };


})(jQuery);

您可以在 jsfiddle

上查看其工作原理

更新: 我的错误是在错误的地方声明变量并使用它们,所以它们被所有实例而不是具体实例使用。感谢 guest271314。他给了我一个如何纠正我的问题的想法。正确的插件如下所示:

;(function($) {

var pluginName = "Pulsar",
    dataKey = "plugin_" + pluginName,
    defaults = {
        key : "color",
        from: "#000",
        to: "#fff",         
        duration: 5,            
        onChange: function(){}
    };


//PRIVATE FUNCTIONS
function Plugin( element, options ) {
    this.element = element;
    this.options = $.extend( {}, defaults, options) ;
    this._defaults = defaults;
    this._name = pluginName;

    //init all required variables
    this.interval = null;
    this.flag = false;

    this.init(options);     
}

function Init(self, key, from, to, duration){
    var element = self.element;

    $(element).css({ 
        WebkitTransition : 'all '+duration+'s',
        MozTransition    : 'all '+duration+'s',
        MsTransition     : 'all '+duration+'s',
        OTransition      : 'all '+duration+'s',
        transition       : 'all '+duration+'s'  
    });     

    var state1, state2; 

    state1 = '{ "'+key+'" : "'+from+'"}';
    state2 = '{ "'+key+'" : "'+to+'"}';

    var state1JSON = JSON.parse(state1);
    var state2JSON = JSON.parse(state2);

    $(element).css(state1JSON);

    if(self.interval != null){          
        clearInterval(self.interval);
    } 
    self.interval = setInterval(function(){
        if(!self.flag){
            $(element).css(state2JSON);
            self.flag=true; 
            self.options.onChange();
        }
        else{
            $(element).css(state1JSON);
            self.flag=false;
            self.options.onChange();
        }               
    }, duration * 1000);
}

//PUBLIC FUNCTIONS
Plugin.prototype = {
    init: function(options){        
        var options = $.extend({}, defaults, options);      
        Init(this, options.key, options.from, options.to, options.duration);
    },
    update: function(key, from, to, duration){          
        Init(this, key, from, to, duration);            
    }
};

$.fn[pluginName] = function ( options ) {
     var plugin = this.data(dataKey);

    // has plugin instantiated ?
    if (plugin instanceof Plugin) {
        // if have options arguments, call plugin.init() again
        if (typeof options !== 'undefined') { 
            plugin.init(options);
        }
    } else {
        plugin = new Plugin(this, options);
        this.data(dataKey, plugin);
    }

    return plugin;
};
})(jQuery);

现在看看它是如何工作的 - jsfiddle

clearInterval(interval)interval = setInterval 之前被调用可能是个问题;也可以尝试将 flag 设置为 this.data()

;(function($) {

  var pluginName = "Pulsar",
    dataKey = "plugin_" + pluginName,
    defaults = {
      key: "color",
      from: "#000",
      to: "#fff",
      duration: 5
    };

  var interval = null;

  function uniqueId() {
    return 'id-' + Math.random().toString(36).substr(2, 16);
  };

  function Init(key, from, to, duration) {
    $(this).css({
      WebkitTransition: 'all ease ' + duration + 's',
      MozTransition: 'all ease ' + duration + 's',
      MsTransition: 'all ease ' + duration + 's',
      OTransition: 'all ease ' + duration + 's',
      transition: 'all ease ' + duration + 's'
    });
    $(this).text(uniqueId());

    var state1, state2;

    state1 = '{ "' + key + '" : "' + from + '"}';
    state2 = '{ "' + key + '" : "' + to + '"}';

    var state1JSON = JSON.parse(state1);
    var state2JSON = JSON.parse(state2);

    $(this).css(state1JSON);

    interval = setInterval(function() {
      if (!$(this).data().flag) {
        $(this).css(state2JSON);
        $(this).data().flag = true;
      } else {
        $(this).css(state1JSON);
        $(this).data().flag = false;
      }
    }.bind(this), duration * 1000);
    return this
  }

  $.fn[pluginName] = function(options) {
    this.data("flag", false);
    var options = $.extend({}, defaults, options);
    return Init.call(this, options.key, options.from, options.to, options.duration);
  };

})(jQuery);

$(document).ready(function() {

  //FOR SINGLE PROPERTY
  $("#pulsar").Pulsar({
    duration: 2,
    key: 'textShadow',
    from: '0px 0px 5px rgba(0, 0, 255, 1)',
    to: '0px 0px 30px rgba(0, 0, 255, 1)'
  });

  setTimeout(function() {
    $("#pulsar2").Pulsar({
      duration: 1,
      key: 'textShadow',
      from: '0px 0px 5px rgba(255, 0, 255, 1)',
      to: '0px 0px 30px rgba(0, 0, 255, 1)'
    });
  }, 5000);

});
body,
html {
  background-color: #000;
}
.pulsar {
  position: absolute;
  font-size: 57px;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.pulsar2 {
  position: absolute;
  font-size: 47px;
  top: 70%;
  left: 50%;
  transform: translate(-50%, -50%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div id="pulsar" class="pulsar">PULSAR</div>
<div id="pulsar2" class="pulsar2">PULSAR 2</div>

jsfiddle https://jsfiddle.net/haevd4ph/5/