【问题标题】:jQuery Plugin Authoring - Set different options for different elementsjQuery Plugin Authoring - 为不同的元素设置不同的选项
【发布时间】:2010-01-29 15:37:18
【问题描述】:

我创建了一个 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 中的选项???

【问题讨论】:

标签: javascript jquery jquery-plugins


【解决方案1】:

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

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

更新为使用每个单独 obj 的 .data。

【讨论】:

  • 太棒了,谢谢。我错过了“将配置附加到每个对象”部分。我最终使用 $.data 来附加配置而不是您的建议。这两种方法有什么优点/缺点吗?我想他们可能差不多。另外,我非常喜欢你的插件设置,非常类似于 jQuery UI。我也采用了 =) 谢谢!!
  • 我不会为每个对象使用 .data,因为插件可能会使用事件委托..另外,如果在没有任何参数的情况下调用插件,那会怎样?在你的例子中什么都不会发生..
  • @vsync 这主要是一个指导方针......可以检查未定义的对象以及初始化为默认值的对象。我还认为数据应用程序应该适用于每个项目,因为每个插入的项目可以在以后进行调整以具有不同的选项。我知道它并不完美……只是想指出似乎在 UI 和其他 jQuery 扩展中使用的一般模式。
  • 我今天想到了一些事情:IMO 最好保存对每个 SELECTOR 的引用,并且对于该选择器,存储适当的选项而不是每个项目本身。假设我有一个插件操作 1000 个输入字段..如果假设我想要一个简单的焦点事件来触发某些东西,那将是不明智的内存管理来处理所有这些..只是一个想法
  • 每个节点的数据不应该只是指向内存中同一个对象的指针吗?
【解决方案2】:

我遇到了同样的问题,但只有传递的函数被覆盖了。直接属性持续存在。

无论如何,为了进一步解释 ~reinierpost 的含义,将您的代码更改为此应该可以。您必须在任何地方传递“选择”,但我认为有必要将选项从插件范围的命名空间中取出。

$.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){

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

【讨论】:

  • 嘿,我在 reinierpost 的帖子之后尝试过,但我仍然遇到同样的问题。问题不是我不能用不同的选项调用单独的,而是在我在一个对象上“初始化”插件之后,然后用不同的选项初始化另一个对象,当我回去调用任何插件函数时项,它使用为第二项而不是第一项提供的设置。我希望这很清楚,如果没有,请告诉我。
  • 我已经更新了我的初始条目,以展示我如何在我的插件中使用这种技术。也许您指的是插件范围的配置对象,而不是在 this.each() 循环中初始化的对象?
  • 是的,它将选项附加到我丢失的对象上。我看到你使用了 $.attached,我最终使用了 $.data ( $(this).data('opts', opts); )。两者之间有什么真正的区别吗?谢谢
  • $.attach 是我在插件中编写的自定义函数 - 它不是 jQuery 核心的一部分,例如 $.data 是 & 根本不相似。
【解决方案3】:

您的选项是插件范围的。将它们移动到 each() 中。 (你为什么要问这个问题?你几乎自己拼出了解决方案。)

【讨论】:

  • 我问是因为我显然不知道解决方案。我已将 this.each 函数之前的所有内容移到 this.each(function() 中,但仍然得到相同的结果。您能澄清一下您的意思吗?
  • 现在我真的很困惑。我的意思是你希望 _option1 等对于每个匹配的元素都是分开的,所以你应该复制它们,例如就像泡菜正在做的那样。您没有向我们展示您以后如何访问这些选项,也许那里还有其他问题。
  • 是的,这就是我的全部问题...稍后访问选项。我没有将配置附加到对象本身。我添加了一个 $(this).data('opts', opts);在 each() 循环中,现在一切都像魅力一样工作。无论如何,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-08
  • 2010-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多