jQueryプラグイン開発の5つの形態の小結

10751 ワード

jQueryプラグインの開発について自分も少し研究しましたが、自分も複数のプラグインを書いたことがあり、自分のチームでもプラグインに関する授業を一度共有しました.最初は複雑なコードを感じていましたが、今再び見たときははっきりしていました.ここで私は自分でまとめたものを分かち合い、私と同じように同じ問題に遭遇した人を助けます.
私が何をしたいのかjavascriptプラグインには以下の特徴があるはずです.
コードは独立したチェーン操作プラグインに対して操作可能な方法を構成することができ、プラグインのライフサイクル制御可能な構成はキャッシュによって拡張され、衝突のない処理イベントエージェント、動的初期化することができる.
*以下のコードは、jQueryが存在すると仮定します.
プラグインの第1の形態
このような状況に直面して、通常はfunctionを定義することによって実現します.
 
  
function pluginName($selector){
    $.each($selector, function () {
        $(this).css("background-color", "#ccc");
        // to do something...
    });
}
// pluginName(document.getElementsByClassName("demo"));

jQueryプラグインの開発について話しているので、私は今このコードをjQueryに拡張しています.コードは以下の通りです.
 
  
// IIFE( );  [ http://suqing.iteye.com/blog/1981591/]
;(function ($) {
    // jQuery.
    // $.extend() $ , $.fn.extend 。 $.fn.xxx ,
    // $(selector).xxx()
    $.fn.extend({
        //
        pluginName: function () {
            //
            // "return", ,
            return this.each(function () {
                //
            });
        }
    });
// jQuery , window,document , .
// })(jQuery, window, document, undefined);
})(jQuery, undefined);
// $(".selector").pluginName().otherMethod();

しかし、まだ遠いので、現在は2つの問題しか解決されていません.
コードが相対的に独立している
チェーン操作
プラグインは操作可能な方法を構成することができ、プラグインのライフサイクル制御可能な構成はキャッシュされ、衝突のない処理イベントエージェントを拡張し、動的に初期化することができる.
プラグインの第2の形態
プラグインにパラメータサポートを追加します.コードは次のとおりです.
 
  
;(function($){
    $.fn.pluginName = function(options) {
        // , “extend”
        var args = $.extend({}, $.fn.pluginName.defaults, options);
        return this.each(function() {
            console.log(args.text);
            // to do something...
        });
    };
    //
    $.fn.pluginName.defaults = {
        text : "hello"
    };
})(jQuery);
// $(".selector").pluginName({
//     text : "hello world!"
// });

パラメータサポートの追加は比較的容易で、また問題を解決します.
コードが相対的に独立している
チェーン操作
プラグインの構成
操作可能な方法があり、プラグインのライフサイクル制御可能な構成は、キャッシュによって拡張され、衝突のない処理イベントエージェント、動的初期化されます.
プラグインの第3の形態
次にメソッドのサポートを追加します.私が前に述べたライフサイクルは制御できます.意味の差は多くありません.例えば、reInit、destoryなどのメソッドを追加してプラグインを制御します.
 
  
;(function($){
    $.fn.pluginName = function (method) {
        // , , ; object , init ;.
        if (methods[method]) {
            //
            // apply obj.method(arg1, arg2, arg3) method(obj, [arg1, arg2, arg3]) .
            // Array.prototype.slice.call(arguments, 1) .
            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 jQuery.pluginName');
        }
    };
    // $.fn.pluginName . "methods" , .
    var methods = {
        /**
         *
         * @param _options
         * @return {*}
         */
        init : function (_options) {
            return this.each(function () {
                var $this = $(this);
                var args = $.extend({}, $.fn.pluginName.defaults, _options);
                // ...
            })
        },
        publicMethod : function(){
            private_methods.demoMethod();
        }
    };
    //
    function private_methods = {
        demoMethod : function(){}
    }
    //
    $.fn.pluginName.defaults = {
    };
})(jQuery);
//
// $("div").pluginName({...});  //
// $("div").pluginName("publicMethod");  //

もう一つの問題を解決する
コードが相対的に独立している
チェーン操作
プラグインの構成
操作可能な方法があり、プラグインのライフサイクルを制御できます.
構成はキャッシュ可能で拡張可能で衝突のない処理イベントエージェント、動的初期化
プラグインの第4の形態
第3の形態のプラグインの修正は、多くのプラグインのニーズに対応することができます.精進して、アップグレードを続けます.第4の形態のプラグインは司徒正美の「javascriptフレームワーク設計」のコードに従っている.オブジェクト向けの知識を少し加えた.
 
  
(function ($) {
    var Plugin = function (element, options) {
        this.element = element;
        this.options = options;
    };
    Plugin.prototype = {
        create: function () {
            console.log(this.element);
            console.log(this.options);
        }
    };
    $.fn.pluginName = function (options) {
        //
        return this.each(function () {
            //
            var ui = $._data(this, "pluginName");
            // ( ), .
            if (!ui) {
                var opts = $.extend(true, {}, $.fn.pluginName.defaults, typeof options === "object" ? options : {});
                ui = new Plugin(this, opts);
                //
                $._data(this, "pluginName", ui);
            }
            //
            if (typeof options === "string" && typeof ui[options] == "function") {
                //
                ui[options].apply(ui, args);
            }
        });
    };
    $.fn.pluginName.defaults = {};
})(jQuery);
// 。

ここで特にキャッシュというものを持ち出すと、プラグインがたくさん使われていて、これは本当にいいものだと思います.従来のオブジェクト向けプラグイン開発では、少なくとも1つの変数を宣言して保存していましたが、私が現在書いているjQueryプラグインにはなく、使うのが面倒でした.初期化されたプラグインをキャッシュしてから、ずいぶん便利になりました.コード$("#target").data(「pluginName」)はオブジェクトを取得できます.まだ何か問題が解決していないか見てみましょう
コードが相対的に独立している
チェーン操作
プラグインの構成
操作可能な方法があり、プラグインのライフサイクルを制御できます.
キャッシュ可能な構成
拡張可能衝突のない処理イベントエージェント、動的初期化
プラグインの第5の形態
上のコードを見て頭がぼんやりしているかどうか、もしそうなら、しばらく休んで、後で帰ってきて、下のコードはもっとすばらしいです.最後の案は比較的全面的だ.シナリオはBootstrapから来ており、以下のコードはBootstrapのbuttonプラグインを例に挙げる.
 
  
!function ($) {
    // ecma262v5 , .
    "use strict";
    // BUTTON PUBLIC CLASS DEFINITION
    // ==============================
    var Button = function (element, options) {
        this.$element = $(element);
        this.options = $.extend({}, Button.DEFAULTS, options);
    };
    Button.DEFAULTS = {
        loadingText: 'loading...'
    };
    Button.prototype.setState = function (state) {
        // ...
    };
    Button.prototype.toggle = function () {
        // ...
    };
    // BUTTON PLUGIN DEFINITION
    // ========================
    var old = $.fn.button; // $.fn.button , 。
    $.fn.button = function (option) {
        return this.each(function () {
            var $this = $(this);
            //
            var data = $this.data('bs.button');
            var options = typeof option == 'object' && option;
            // ,
            if (!data) $this.data('bs.button', (data = new Button(this, options)));
            if (option == 'toggle') data.toggle();
            else if (option) data.setState(option)
        })
    };
    // ① ,
    $.fn.button.Constructor = Button;
    //
    // : $.fn.button.Constructor.newMethod = function(){}
    // : $btn.button("newMethod");
    // ②
    $.fn.button.noConflict = function () {
        $.fn.button = old;
        return this
    };
    // ③ ,
    $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {
        var $btn = $(e.target);
        //
        if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn');
        // , ,
        $btn.button('toggle');
        e.preventDefault();
    });
}(jQuery);

まだ何か問題が解決していないか見てみましょう
コードが相対的に独立している
チェーン操作
プラグインの構成
操作可能な方法があり、プラグインのライフサイクルを制御できます.
キャッシュ可能な構成
拡張性
衝突処理なし
イベントエージェント、動的初期化
補足
現在のプラグインでは、jQueryとZeptoを同時に適合させることができるようにするか、AMDまたはCMD仕様をサポートする必要があるなど、柔軟性が求められています.
jQueryとZeptoをサポート
 
  
if (window.jQuery || window.Zepto) {
  (function ($) {
      // plugin code...
  })(window.jQuery || window.Zepto);
}

ミドルウェアサポート、node
 
  
if (typeof(module) !== 'undefined')
{
  module.exports = pluginName;
}
requirejs(AMD) support
if (typeof define === 'function' && define.amd) {
  define([], function () {
      'use strict';
      return pluginName;
  });
}
seajs(CMD) support
if (typeof define === 'function') {
  define([], function () {
      'use strict';
      return pluginName;
  });
}

ふーん、問題はすべて解決しました.コードが読めないところがあればもっと見てもいいです.後ろのいくつかが読めなくても大丈夫ですが、実際の開発では、前のいくつかが十分です.強調するには、高級な書き方ほど良いわけではなく、自分のプロジェクトのニーズに応じて合理的な選択をしなければならない.
さて、今日のまとめはここまでですが、もっと良いプラグインの開発方法があれば、教えてください.本文が好きになってほしい.