星期四, 10月 02, 2014

[jQuery Plugin] 撰寫jQuery plugin的寫作樣式

太久沒寫jQuery外掛了,找了一些資料來複習一下。
這篇文章記錄一下自已喜歡用的jquery plugin寫作方式。
初學者建議讀一下這篇: http://learn.jquery.com/plugins/

外掛功能


  1. 保持jQuery物件鏈結 (非常重要)
  2. 提供公有方法(有時候在init plugin之後,可能會需要公有方法能變更plugin的行為或屬性)
  3. 提供預設的參數設定
  4. 儲存產生plugin 物件的參考 (基於第二個方法)

方法一: 類似bootstrap的解法

最後參考這篇 Things I learnt creating a jQuery Plugin (Part I),作者也基於這個寫作方式,寫了一個bootstrap的tagger外掛: https://github.com/acanimal/tagger.js

;(function($) {
    //define plugin name
    var pluginName =  'jqueryPlugin';
    
    //create plugin class
    function Plugin (element,options){
        
        this.el = element;
        this.$el = $(element);
        
        this.options = $.extend({}, $.fn[pluginName].defaults, options);
       
        //constrctor
        this.init();
        
        return this;
    };
    
    Plugin.prototype.name = pluginName;
    Plugin.prototype.version =  '0.0.1';
    
    Plugin.prototype = {
        
        init : function(){
            
            var plugin = this;
        },
        
        /**
         * The 'destroy' method is were you free the resources used by your plugin:
         * references, unregister listeners, etc.
         *
         * Remember to unbind for your event:
         *
         * @example
         * this.$someSubElement.off('.' + pluginName);
         *
         * Above example will remove any listener from your plugin for on the given
         * element.
         */
        destroy: function() {

            // Remove any attached data from your plugin
            this.$el.removeData();
        },
        
         /**
         * Write public methods within the plugin's prototype. They can 
         * be called with:
         *
         * @example
         * $('#element').jqueryPlugin('somePublicMethod','Arguments', 'Here', 1001);
         *  
         * @param  {[type]} foo [some parameter]
         * @param  {[type]} bar [some other parameter]
         * @return {[type]}
         */
        pubMethod : function(){
            
        }
        
    }
 
    /**
     * This is a real private method. A plugin instance has access to it
     * @return {[type]}
     */
    var privateMethod = function() {
        console.log("privateMethod");
        console.log(this);
    };
    
    // Plugin wrapper around the constructor,
    $.fn[pluginName] = function(options) {
        
        var args = arguments;

        if (options === undefined || typeof options === 'object') {
            // Create a plugin instance for each selected element.
            return this.each(function() {
                if (!$.data(this, 'plugin_' + pluginName)) {
                    $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
                }
            });
        } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
            // Call a pluguin method for each selected element.
            if (Array.prototype.slice.call(args, 1).length == 0 && $.inArray(options, $.fn[pluginName].getters) != -1) {
                // If the user does not pass any arguments and the method allows to
                // work as a getter then break the chainability
                var instance = $.data(this[0], 'plugin_' + pluginName);
                return instance[options].apply(instance, Array.prototype.slice.call(args, 1));
            } else {
                // Invoke the speficied method on each selected element
                return this.each(function() {
                    var instance = $.data(this, 'plugin_' + pluginName);
                    if (instance instanceof Plugin && typeof instance[options] === 'function') {
                        instance[options].apply(instance, Array.prototype.slice.call(args, 1));
                    }
                });
            }
        }
    }

     /**
     * Names of the pluguin methods that can act as a getter method.
     * @type {Array}
     */
    $.fn[pluginName].getters = ['pubMethod'];
    
     /**
     * Default options
     */
    $.fn[pluginName].defaults = {
         defaultOption: "I'm a default option"
    };
    
})(jQuery);



方法二: jQuery Widget

使用jQuery UI 提供的widget factory,如果有引用jquery UI lib的話,直接套用這個是蠻快速的

http://stackoverflow.com/questions/1117086/how-to-create-a-jquery-plugin-with-methods


Reference:

The Ultimate Guide to Writing jQuery Plugins
An Improved Version of the jQuery Plugin Template
Things I learnt creating a jQuery Plugin (Part I)

沒有留言:

張貼留言

留個話吧:)