一个带有选项和可访问方法的jQuery插件模板?

5

我希望创建一个具有可访问方法和选项的插件,用于复杂的插件。我需要使方法在插件外部可以访问,因为如果有人向DOM添加了内容,则需要更新它(这样我们就不需要再次运行完整的插件)。

我以前看到过像这样的插件,但现在找不到它们,所以无法查看它们。我对JavaScript仍然很陌生,任何帮助都将受益匪浅。

如果我们仍然可以全局覆盖选项,那将很好。

我想如何使用该插件:

// options
$('#someid').myplugin({name: 'hello world'});

// methods(would be nice if we can use this)
$('#someid').myplugin('update');

//我的旧插件包装器

;(function($, window, document, undefined){

    $.fn.pluginmyPlugin = function(options) { 

        options = $.extend({}, $.fn.pluginmyPlugin.options, options); 

            return this.each(function() {  

                var obj = $(this);

                // the code 
            });     
        };

        /**
        * Default settings(dont change).
        * You can globally override these options
        * by using $.fn.pluginName.key = 'value';
        **/
        $.fn.pluginmyPlugin.options = {
            name: '',
                            ...         
        };

})(jQuery, window, document);

更新

在查看jQuery文档后,我已经编写了以下代码,请告诉我代码是否有问题,是否可以更好地构建...

;(function($, window, document, undefined){

    var methods = {

        init : function( options ) {

            options = $.extend({}, $.fn.pluginmyPlugin.options, options); 

            return this.each(function(){

            alert('yes i am the main code')

            });
        },
        update : function( ) {
             alert('updated')
        }
    };

    $.fn.pluginmyPlugin = function(method) { 

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

    };

        /**
        * Default settings(dont change).
        * You can globally override these options
        * by using $.fn.pluginName.key = 'value';
        **/
        $.fn.pluginmyPlugin.options = {
            name: 'john doe',
            //....
        };

})(jQuery, window, document);

检查这个链接:http://docs.jquery.com/Plugins/Authoring - Cristi Pufu
谢谢,我已经看了并使用了这个。我已经添加了我现在要使用的插件,如果你发现这个插件有什么问题,请告诉我。谢谢! - user759235
4个回答

3

另一种选择:

var Plugin = function($self, options) {
  this.$self = $self;
  this.options = $.extend({}, $.fn.plugin.defaults, options);
};

Plugin.prototype.display = function(){
  console.debug("Plugin.display");
};

Plugin.prototype.update = function() {
  console.debug("Plugin.update");
};

$.fn.plugin = function(option) {
  var options = typeof option == "object" && option;

  return this.each(function() {
    var $this = $(this);
    var $plugin = $this.data("plugin");

    if(!$plugin) {
      $plugin = new Plugin($this, options);
      $this.data("plugin", $plugin);
    }

    if (typeof option == 'string') {
      $plugin[option]();
    } else {
      $plugin.display();
    }
  });
};

$.fn.plugin.defaults = {
  propname: "propdefault"
};

使用方法:

$("span").plugin({
  propname: "propvalue"
});

$("span").plugin("update");

这很像Twitter Bootstrap的JavaScript模板。但是,并非完全从那里采取。我长期以来一直使用.data()
不要忘记适当地包装它。

看起来不错,但是我读到 jQuery 2.0 版本后,数据将被删除了...对吗?我对 data() 不是很熟悉,我只用它来处理 data- 元素。 - user759235
@user759235,我想要一个支持关于.data()移除的评论的参考资料。 - Alexander
@user759235,我建议你再读一遍。你误解了被删除的内容,实际上是 $.fn.data("events") 而不是 $.fn.data。此外,这与2.0无关,这是1.8版本的更新日志。 - Alexander
啊,好的,很抱歉啊 :-) - user759235
我正在使用这个版本,并查看引导版本...感谢您的帮助! - user759235
显示剩余7条评论

2
如果您想使用此插件,可以按照以下步骤操作:
// Init plugin
$('a').myplugin({
    color: 'blue'
});

// Call the changeBG method
$('a').myplugin('changeBG')
    // chaining
    .each(function () {
        // call the get method href()
        console.log( $(this).myplugin('href') );
    });

如果您需要每个元素独立的插件实例:

$('a').each(function () {
    $(this).myplugin();
});

您将希望按照以下方式设置插件:

/*
 *  Project: 
 *  Description: 
 *  Author: 
 *  License: 
 */

// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
;(function ( $, window, document, undefined ) {

    // undefined is used here as the undefined global variable in ECMAScript 3 is
    // mutable (ie. it can be changed by someone else). undefined isn't really being
    // passed in so we can ensure the value of it is truly undefined. In ES5, undefined
    // can no longer be modified.

    // window is passed through as local variable rather than global
    // as this (slightly) quickens the resolution process and can be more efficiently
    // minified (especially when both are regularly referenced in your plugin).

    var pluginName = "myplugin",
        // the name of using in .data()
        dataPlugin = "plugin_" + pluginName,
        // default options
        defaults = {
            color: "black"
        };

    function privateMethod () {
        console.log("private method");
    }

    // The actual plugin constructor
    function Plugin() {
        /*
         * Plugin instantiation
         *
         * You already can access element here
         * using this.element
         */
         this.options = $.extend( {}, defaults );
    }

    Plugin.prototype = {

        init: function ( options ) {

            // extend options ( http://api.jquery.com/jQuery.extend/ )
            $.extend( this.options, options );

            /*
             * Place initialization logic here
             */
            this.element.css( 'color', 'red' );
        },

        destroy: function () {
            // unset Plugin data instance
            this.element.data( dataPlugin, null );
        },

        // public get method
        href: function () {
            return this.element.attr( 'href' );
        },

        // public chaining method
        changeBG: function ( color = null ) {
            color = color || this.options['color'];
            return this.element.each(function () {
                // .css() doesn't need .each(), here just for example
                $(this).css( 'background', color );
            });
        }
    }

    /*
     * Plugin wrapper, preventing against multiple instantiations and
     * allowing any public function to be called via the jQuery plugin,
     * e.g. $(element).pluginName('functionName', arg1, arg2, ...)
     */
    $.fn[pluginName] = function ( arg ) {

        var args, instance;

        // only allow the plugin to be instantiated once
        if (!( this.data( dataPlugin ) instanceof Plugin )) {

            // if no instance, create one
            this.data( dataPlugin, new Plugin( this ) );
        }

        instance = this.data( dataPlugin );

        /*
         * because this boilerplate support multiple elements
         * using same Plugin instance, so element should set here
         */
        instance.element = this;

        // Is the first parameter an object (arg), or was omitted,
        // call Plugin.init( arg )
        if (typeof arg === 'undefined' || typeof arg === 'object') {

            if ( typeof instance['init'] === 'function' ) {
                instance.init( arg );
            }

        // checks that the requested public method exists
        } else if ( typeof arg === 'string' && typeof instance[arg] === 'function' ) {

            // copy arguments & remove function name
            args = Array.prototype.slice.call( arguments, 1 );

            // call the method
            return instance[arg].apply( instance, args );

        } else {

            $.error('Method ' + arg + ' does not exist on jQuery.' + pluginName);

        }
    };

}(jQuery, window, document));

注意:

  • 此模板不会在每次方法调用时使用.each(),您需要在需要时使用.each()
  • 允许重新初始化插件,但只会创建一个实例
  • 包含destroy方法的示例

参考:https://github.com/jquery-boilerplate/jquery-boilerplate/wiki/jQuery-boilerplate-and-demo


1
你尝试过jQuery UI Widget Factory吗?
起初可能有点陡峭的学习曲线,但现在我很喜欢它,可以处理选项和默认值,并允许方法,将所有内容紧密包装得非常漂亮 :)

编辑

jQuery UI Widget Factory是jQuery UI库的一个独立组件,提供了一种简单、面向对象的方式来创建有状态的jQuery插件。

有状态插件和Widget Factory介绍

我认为在大多数情况下,额外的开销并不需要太担心。现在我使用coffescript编写代码,所有内容都被编译、压缩和gzip,所以偶尔多出几行代码并没有太大影响。我的网站速度研究表明,HTTP请求的数量是一个很重要的问题 - 曾经的同事就是为基于浏览器的游戏工作的,他非常注重速度。


一位前同事为我安排了这个,但我认为开销不大。 - CodeMonkey
添加了更多细节 :) - CodeMonkey
尽管jQuery UI项目已经基本停滞不前,但主要的jQuery项目仍然提到了这种创建有状态插件的技术,并指出:“它可以独立于jQuery UI使用。” https://learn.jquery.com/plugins/stateful-plugins-with-widget-factory/ - peater

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接