jQuery插件创作 - 为不同的元素设置不同的选项

时间:2010-01-29 15:37:19

标签: javascript jquery jquery-plugins

我创建了一个jQuery插件,除了能够在不同的对象上调用插件以及保留给定选项的每个对象之外,它运行良好。问题是,如果我在一个对象上调用插件,请说:

$('#myDiv1').myPlugin({
    option1: 'some text',
    option2: true,
    option3: 'another option value'
});

然后再次在另一个对象上调用该插件,例如:

$('#myDiv2').myPlugin({
    option1: 'different text',
    option2: false,
    option3: 'value for myDiv2'
});

然后,如果我回去尝试用#myDiv1做一些事情,需要原始选项仍然完整,即:

$('#myDiv1').myPlugin.update();

它没有原始选项,但它们将被#myDiv2的选项覆盖。这样做的正确方法是什么,以便每个对象都保留给它的原始选项? (以下是我在插件中所做的一些示例代码)

(function($) {
$.fn.myPlugin = function(options) {

    // build main options before element iteration
    var opts = $.extend({}, $.fn.myPlugin.defaults, options);

    _option1 = opts.option1;
    _option2 = opts.option2;
    _option3 = opts.option3;

    // iterate all matched elements
    return this.each(function() {
        callPluginFunctions( this, opts );
    });

};

    ....code continued....

我意识到这是某种范围蔓延或某种东西。那么,我如何让我的选择保持附加并保持原始对象(即#myDiv1)的范围。

编辑:在进行一些研究时,我发现您可以使用jQuery的.data函数将数据存储到对象,文档说jQuery UI广泛使用它。这里适当的做法是使用.data将选项存储在对象上,然后在以后引用时使用存储在.data中的选项???

3 个答案:

答案 0 :(得分:16)

首先,您通常希望在扩展方法中处理该命令。其次,您应该将配置附加到每个项目......

(function($){
var defaultOptions = { /* default settings here */ };

//called on the native object directly, wrap with $(obj) if needed.
function initializeObject(obj, options) {
  //assign the options to the object instance.
  $(obj).data('myPlugin-options', $.extend(defaultOptions, options) );
  //do other initialization tasks on the individual item here...
}

function updateObject(obj) {
  // use $(obj).data('myPlugin-options');
}

function setOption(obj, key, value) {
  var d = $(obj).data('myPlugin-options');
  d[key] = value;
  $(obj).data('myPlugin-options', d);
}

$.fn.myPlugin = function(command, option, val) {
  if (typeof command == "object") {
    //initialization
    return this.each(function(){
      initializeObject(this, command);
    });
  }
  if (typeof command == "string") {
    // method or argument query
    switch (command.toLowerCase()) {
      case 'option':
        //get value, return the first item's value
        if (typeof val == undefined) return this.eq(0).data('myPlugin-options')[option];
        //set option value
        return this.each(function() {
          setOption(this, option, val);
        });

      case 'update':
        return this.each(function() {
          updateObject(this);
        });
      //other commands here.
    }
  }
}
})(jQuery)

使用上面的示例,您有一个jQuery扩展的通用模板,通常可以使用以下约定。

Initialization:
  $(...).myPlugin({ initialization-options-here });
Command:
   $(...).myPlugin('command-name'); //where command can be update, etc.
Get Option:
  var myValue = $(...).myPlugin('option', 'option-name');
Set Option:
  $(...).myPlugin('option', 'option-name', newValue);

更新为使用.data off of each individual obj。

答案 1 :(得分:0)

我遇到了同样的问题,但只有被传递的功能被覆盖了。直线房产持续存在。

无论如何,要进一步解释~reinierpost意味着什么,将代码更改为此应该有效。你必须在任何地方传递'opts',但我认为有必要从插件范围的命名空间中取出选项。

$.fn.myPlugin = function(options) {

    // iterate all matched elements
    return this.each(function() {
        // build main options before element iteration
        var opts = $.extend({}, $.fn.myPlugin.defaults, options);
        callPluginFunctions( this, opts );
    });
};

编辑:这是我的插件中的代码

this.each(function() {
    var thisConfig = config;
    thisConfig = $.extend(thisConfig,settings);
    $.attach($(this),thisConfig);
});

...

$.attach = function($target,config){

所以我没有插件范围的“配置” - 就在每个函数内部。

答案 2 :(得分:-1)

您的选项是插件范围的。将它们移动到每个()中。 (你为什么问这个问题?你自己就解决了这个问题。)