簡單的JavaScript組件化實現

jopen 9年前發布 | 13K 次閱讀 JavaScript開發 JavaScript

 

作為一名前端菜鳥,最近看react例子,根據理解自己也簡單實現了一下組件的繼承和事件機制。

代碼在 這里

原始的組件寫法

(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! 簡單的JavaScript組件化實現 </div>

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

處理一套風格相似的組件的時候,通過傳遞不同的參數來控制不同的ui顯示和邏輯代碼執行,確實可以解決問題,隨著功能的一步步增加,這個組件就變 得越來越臃腫,代碼耦合成度變高,到最后自己都搞不清楚每個參數不同值代表的意思。況且在團隊中都是多個人維護同一個組件,這簡直就是一場悲劇。從此mm 的態度也變得不好,你還坑害了維護組件的好基友。

繼承

這時候面向對象的思維就出場了

簡單的JavaScript組件化實現

我們發現設置titile, 關閉窗體是大家共有的功能。這里可以抽象成一個基礎組件,新的組件繼承這個組件即可。

</div>

(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()實現

這時需求mm又來了,需求mm說當用戶點擊確定之后要加一個其他功能,其實第一個例子中,我們也可以實現這樣的功能。我們可以傳遞一個callback onFoo。

我們需要引入一種更加優雅的方式,參考node的 事件機制 。大家知道,Node.js能夠在眾多的后端JavaScript技術之中脫穎而出,正是因其基于事件的特點而受到歡迎。

事件機制

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

(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函數來監聽。寫代碼好像突然變得好爽好舒服。

最后記得提供一個銷毀組件的方法,一個簡單的組件就完成了。

完整的代碼在 這里

</div>

當然要更好的組件還需要提供

  1. 模板機制

  2. 雙向綁定

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!