簡單的JavaScript組件化實現

做爲一名前端菜鳥,最近看react例子,根據理解本身也簡單實現了一下組件的繼承和事件機制。javascript

代碼在這裏html

原始的組件寫法

(function($) {
    $.pluginName = function(element, options) {
        var defaults = {
            title: '',
            content: '',
            showOKBtn: 1, // 顯示肯定按鈕
            showCCBtn: 1, // 顯示取消按鈕
            onFoo: function() {} // callback
        }

        var plugin = this;
        plugin.settings = {}

        var $element = $(element);

        plugin.init = function(options) {
            this.settings = $.extend({}, defaults, options);
            this.initNode(options);
        }

        // public method.
        plugin.show = function() {
            // ...
        }
        plugin.hide = function() {
            // ...    
        }

        plugin.initNode = function(options) {
            var $okBtn = $element.find(''),
                $content = $element.find('');
            // ....
            // 部分邏輯
            $content.text(plugin.settings.content);
            $okBtn.on('click', $.proxy(this.onOk, this));
        }

        plugin.onOk = function(){
            this.hide();
            plugin.settings.onFoo();
        }

        plugin.init();
    }

    $.fn.pluginName = function(options) {
        return this.each(function() {
            if (undefined == $(this).data('pluginName')) {
                var plugin = new $.pluginName(this, options);
                $(this).data('pluginName', plugin);
            }
        });
    }
})(jQuery);

// 使用
var template = '<div>...彈框html...</div>';
$(template).pluginName({
    content: '肯定刪除該地址'
}).show();

通常咱們寫得入門級jquery組件,基本就是這樣一個模板。
這裏咱們實現了一個基本的彈窗組件,也完成了需求方的要求,oh ye!enter image description here前端

某天需求mm說咱們要加一個confirm信息的彈框,只要一個肯定按鈕!!還好還好。組件中原本就加了options.showCCBtn的配置,實例化的時候傳一個參數就能夠了。分分鐘解決了mm的問題,還獲得mm的讚許,想一想都有點小激動呢。java

處理一套風格類似的組件的時候,經過傳遞不一樣的參數來控制不一樣的ui顯示和邏輯代碼執行,確實能夠解決問題,隨着功能的一步步增長,這個組件就變得愈來愈臃腫,代碼耦合成度變高,到最後本身都搞不清楚每一個參數不一樣值表明的意思。何況在團隊中都是多我的維護同一個組件,這簡直就是一場悲劇。今後mm的態度也變得很差,你還坑害了維護組件的好基友。node

繼承

這時候面向對象的思惟就出場了
enter image description here
咱們發現設置titile, 關閉窗體是你們共有的功能。這裏能夠抽象成一個基礎組件,新的組件繼承這個組件便可。react

(function() {
    var BaseWindon = Kclass.extend({
        init: function(options){
           //公共功能 
            $titleElm.text(options.title);
            $closeElm.on('click', $.proxy(this.close, this));
        },
                    // 銷燬
        destroy: function(){
                    
        }
        close: function(){

        }
    };
    return BaseWindon;
})()

 在子類中 require('BaseWindon');

 (function() {
    var AddAddressWindon = BaseWindon.extend({
        init: function(options){
            // 調用parent的init
            this.supr();
        },
        validate: function(){

        },
        // 組件本身的功能
        submit: function(){

        }
    };
    return AddAddressWindon;
})()

javascript oo的實現有不少種,我用了ded/klass,supr的實現比較巧妙。主要原理爲:獲取方法的代碼字符串,經過正則檢測字符串中是否包含 supr,若包含, 則改寫該方法,在改寫的方法中動態的改變this.supr,使其指向父類同名方法,以完成調用父類方法的目的。具體的原理可看參考野生小技巧--繼承中的super()實現jquery

這時需求mm又來了,需求mm說當用戶點擊肯定以後要加一個其餘功能,其實第一個例子中,咱們也能夠實現這樣的功能。咱們能夠傳遞一個callback onFoo。git

咱們須要引入一種更加優雅的方式,參考node的事件機制。你們知道,Node.js可以在衆多的後端JavaScript技術之中脫穎而出,正是因其基於事件的特色而受到歡迎。github

事件機制

事件機制對應着一種設計模式-觀察者模式。後端

(function() {
    var win = new BaseWindow();

    win.on('ok', function(){
        console.log('on ok!');
    });

    win.emit('ok');  
    // log  --- on ok!
})()

實如今這裏

顯然事件驅動的方式更加優雅,相比之下第一種手動觸發callback的方式顯得有點out。事件機制的方式,在監聽on和觸發emit的時機上也顯得更加靈活,對於只須要觸發一次的callback,你只須要用once函數來監聽。寫代碼好像忽然變得好爽好舒服。

最後記得提供一個銷燬組件的方法,一個簡單的組件就完成了。
完整的代碼在這裏

固然要更好的組件還須要提供

  1. 模板機制

  2. 雙向綁定

相關文章
相關標籤/搜索