创建一个jQuery插件的实例

时间:2018-03-12 16:24:27

标签: javascript jquery

我有几个页面,我希望允许用户内联编辑许多字段并更新服务器数据库。为了实现这一点,我的目的是创建一个jQuery插件,我可以通过配置选项的典型传递,并使用ajax来保存结果。

(function($){
    var methods = {
        init    : function (options) {return this.each(function () {/* ... */});},
        method1 : function ()        {return this.each(function () {/* ... */});},
        method2 : function ()        {return this.each(function () {/* ... */});}
    };

    $.fn.myEditPlugin= function(method) {
        if (methods[method]) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));   //Line 10
        } else if (typeof method === 'object' || ! method) {
            return methods.init.apply(this, arguments);                                     //Line 12
        } else {
            $.error('Method ' +  method + ' does not exist on jQuery.myEditPlugin');
        }    
    };
    }(jQuery)
);

对于每个单独的页面,有几个共同的选项(即url端点,记录的主键等),我不想在应用插件时重复每个选项。

最初,我只是在每个页面上定义一个函数,它接受一些输入并将公共选项应用于每个页面。

function wrapEdit(e,options) {
  options.url='/page1/etc';
  options.pk=document.getElementById('pk').value;
  return $(e).myEditPlugin(options);
}
wrapEdit('.someclass',{foo:123});

这对我来说似乎并不那么专业,所以在我的痴迷追求中,我想我会创建一个可以通过常用选项的类,它会应用插件。

class WrapEdit(options)
{
  constructor(options) {
    this.options = options;
  }
  this.applyIndividualOptions=function(e, options) {
     return $(e).myEditPlugin(Object.assign({}, this->options, options));
  }
}

var wrapEdit=new WrapEdit({url: '/page1/etc', pk: document.getElementById('pk').value});
wrapEdit.applyIndividualOptions('.someclass',{foo:123});

更好,但不是非常jQueryish,因为我将传递select元素,而不是直接将插件应用于jQuery的典型元素。

是否可以创建一个jQuery插件实例来保存以前定义的数据?可能类似于以下内容:

$.myEditPlugin({url: '/page1/etc', pk: document.getElementById('pk').value});
$('.someclass').myEditPlugin({foo:123});  //Will also pass previously defined url and pk to myEditPlugin

或者最好每页创建一个自定义jQuery插件,只需添加额外选项并启动真正的插件......

$.fn.myEditPluginInstance = function(options) {
    return this.myEditPlugin(Object.assign({url: '/page1/etc', pk: document.getElementById('pk').value}, options));    
};

1 个答案:

答案 0 :(得分:1)

创建一个针对jquery集合调用的函数

基本思想是在对插件进行任何调用之前在jQuery.fn中定义一个新属性(函数)(换句话说,执行与应用程序相关的任何代码)。您可以使用“立即调用的函数表达式”(a.k.a. IIFE)来屏蔽您的插件API。然后您必须遍历集合并执行您的插件需要应用于集合项的任何代码。

基本骨架

(function ($) {
    // Enclosed scope (IIFE)
    // You can define private API/variables in here
    // …

    // Once your plugin API is ready, you have to apply the magic to each item
    // in the collection in some ways. You must add a property to jQuery.fn object.
    $.fn.myAwesomePlugin = function(Opt) {
      var defaultConfig = {option1: 'someValue' /*, …*/};

      // Eval supplied Opt object (Validate, reject, etc.)
      // If all goes well, eventually merge the object with defaults.
      $.extend(defaultConfig, Opt);

      // Apply the magic against each item in the jQuery collection
      // (Your plugin may not need to use "each" function though)
      // Return the jQuery collection anyway to keep chaining possible.
      // Once again, this is not required, your plugin may return something else depending on the options passed earlier for instance.
      return this.each(function(el, idx) {
        // Your plugin magic applied to collection items…
      });
    }

})(jQuery);

您应该可以在声明后立即调用您的插件$('someSelector').myAwesomePlugin();

简单的实施示例

(function ($) {
    let required = {url: null, pk: null}
      // Function to be executed upon first call to the plugin
      , populateCommons = () => {
        let ep = $('#someNode').data('endpoint')
            , pk = document.querySelector('#pk')
            ;
        // Basic tests to alert in case the page 
        // doesn't comply with the plugin requirements
        if( typeof ep !== 'string' || !/^\/[a-z]+/.test(ep) || !pk) {
            throw ` "myEditPlugin" init phase error:
            Detected endpoint: '${ep}'
            Is PK value found: ${!!pk}
            `;
        }
        [required.url, required.pk] = [ep, +pk.value];
      };

    $.fn.myEditPlugin = function(Opt) {
      let allOpts;
      // First call will trigger the retrival of common data
      // that should be available as static data somewhere every page source.
      !required.url && populateCommons();
      allOpts = $.extend({}, Opt, required);
      
      return this.each(function(el, idx) {
        // Your logic here, request
        console.log("Payload is", allOpts);
      });
    }
    
})(jQuery);

function debounce(fn, time) {
  debounce.timer && (clearTimeout(debounce.timer));
  debounce.timer = setTimeout(() => (fn(), debounce.timer = null), time);
}

$('[type="text"]').keydown(function(e){
   debounce(() => this.value && $(this).myEditPlugin({foo:this.value, bar: 'Contextual value'}), 2000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input id="pk" type="hidden" value="5">

<div id="someNode" data-endpoint="/api/endpoint">
  Editing the below input will trigger the plug-in code
</div>

<input type="text" title="Edit me"/>

相关documentation here