簡單的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!
</div>
某天需求mm說我們要加一個confirm信息的彈框,只要一個確定按鈕!!還好還好。組件中本來就加了options.showCCBtn的配置,實例化的時候傳一個參數就可以了。分分鐘解決了mm的問題,還得到mm的贊許,想想都有點小激動呢。
處理一套風格相似的組件的時候,通過傳遞不同的參數來控制不同的ui顯示和邏輯代碼執行,確實可以解決問題,隨著功能的一步步增加,這個組件就變 得越來越臃腫,代碼耦合成度變高,到最后自己都搞不清楚每個參數不同值代表的意思。況且在團隊中都是多個人維護同一個組件,這簡直就是一場悲劇。從此mm 的態度也變得不好,你還坑害了維護組件的好基友。
繼承
這時候面向對象的思維就出場了
我們發現設置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函數來監聽。寫代碼好像突然變得好爽好舒服。