作者: 京東零售 陳震
一、 什么是Backbone
在前端的發展道路中,前端框架元老之一jQuery對繁瑣的DOM操作進行了封裝,提供了鏈式呼叫、各類選擇器,屏蔽了不同瀏覽器寫法的差異性,但是前端開發程序中依然存在作用域污染、代碼復用度低、冗余度高、資料和事件系結煩瑣等痛點,
5年后,Backbone橫空出世,通過與Underscore、Require、Handlebar的整合,提供了一個輕量和友好的前端開發解決方案,其諸多設計思想對于后續的現代化前端框架發展起到了舉足輕重的作用,堪稱現代前端框架的基石,
通過對Backbone前端框架的學習,讓我們領略其獨特的設計思想,
二、 核心架構
按照MVC框架的定義,MVC是用來將應用程式分為三個主要邏輯組件的架構模式:模型,視圖和控制器,這些組件被用來處理一個面向應用的特定開發, MVC是最常用的行業標準的Web開發框架,以創建可擴展的專案之一, Backbone.js為復雜WEB應用程式提供模型(models)、集合(collections)、視圖(views)的結構,
? 其中模型用于系結鍵值資料,并通過RESRful JSON介面連接到應用程式;
? 視圖用于UI界面渲染,可以宣告自定義事件,通過監聽模型和集合的變化執行相應的回呼(如執行渲染),
如圖所示,當用戶與視圖層產生互動時,控制層監聽變化,負責與資料層進行資料互動,觸發資料Change事件,從而通知視圖層重新渲染,以實作UI界面更新,更進一步,當資料層發生變化時,由Backbone提供了資料層和服務器資料共享同步的能力,
其設計思想主要包含以下幾點:
?資料系結(依賴渲染模板引擎)、事件驅動(依賴Events)
?視圖組件化,并且組件有了生命周期的概念
?前端路由配置化,實作頁面區域重繪
這些創新的思想,在現代前端框架中進一步得到了繼承和發揚,
三、 部分原始碼決議
Backbone極度輕量,編譯后僅有幾kb,貫穿其中的是大量的設計模式:工廠模式、觀察者模式、迭代器模式、配接器模式……,代碼流暢、實作程序比較優雅,按照功能拆分為了Events、Model、Collection、Router、History、View等若干模塊,這里摘取了部分精彩原始碼進行了決議,相信對我們的日常代碼開發也有一定指導作用:
(1)迭代器
EventsApi起到一個迭代器分流的作用,對多個事件進行決議拆分,設計的非常經典,執行時以下用法都是合法的:
?用法一:傳入一個名稱和回呼函式的物件
modal.on({
"change": change_callback,
"remove": remove_callback
})
?用法二:使用空格分割的多個事件名稱系結到同一個回呼函式上
model.on("change remove", common_callback)
實作如下:
var eventsApi = function(iteratee, events, name, callback, opts) {
var i = 0, names;
if(name && typeof name === 'object') {
// 處理第一種用法
if(callback !== void 0 && 'context' in opts && opts.context === void 0) opts.context = callback;
for(names = _.keys(names); i < names.length; i++) events = eventsApi(iteratee, events, names[i], name[names[i]], opts);
} else if(name && eventSplitter.test(name)) {
// 處理第二種用法
for(names = name.split(eventSplitter); i < names.length; i++) events = iteratee(events, names[i], callback, opts);
} else {
events = iteratee(events, name, callback, opts);
}
return events;
}
(2)監聽器
用于一個物件監聽另外一個物件的事件,例如,在A物件上監聽在B物件上發生的事件,并且執行A的回呼函式:
A.listenTo(B, "b", callback)
實際上這個功能用B物件來監聽也可以實作:
B.on("b", callback, A)
這么做的好處是,方便對A創建、銷毀邏輯的代碼聚合,并且對B的侵入程度較小,實作如下:
Events.listenTo = function(obj, name, callback) {
if(!obj) return this;
var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
// 當前物件的所有監聽物件
var listeningTo = this._listeningTo || (this._listeningTo = {});
var listening = listeningTo[id];
if(!listening) {
// 創建自身監聽id
var thisId = this._listenId || (this._listenId = _.uniqueId('l'));
listening = listeningTo[id] = {obj: obj, objId: id, id: thisId, listeningTo: listeningTo, count: 0};
}
// 執行物件系結
internalOn(obj, name, callback, this, listening);
return this;
}
(3)Model值set
通過option-flags兼容賦值、更新、洗掉等操作,這么做的好處是融合公共邏輯,簡化代碼邏輯和對外暴露api,實作如下:
set: function(key, val, options) {
if(key == null) return this;
// 支持兩種賦值方式: 物件或者 key\value
var attrs;
if(typeof key === 'object') {
attrs = key;
options = val;
} else {
(attrs = {})[key] = val;
}
options || (options = {});
……
var unset = options.unset;
var silent = options.silent;
var changes = [];
var changing = this._changing; // 處理嵌套set
this._changing = true;
if(!changing) {
// 存盤變更前的狀態快照
this._previousAttributes = _.clone(this.attributes);
this.changed = {};
}
var current = this.attributes;
var changed = this.changed;
var prev = this._previousAttributes;
for(var attr in attrs) {
val = attrs[attr];
if(!_.isEqual(current[attr], val)) changes.push(attr);
// changed只存盤本次變化的key
if(!_.isEqual(prev[attr], val)) {
changed[attr] = val;
} else {
delete changed[attr]
}
unset ? delete current[attr] : (current[attr] = val)
}
if(!silent) {
if(changes.length) this._pending = options;
for(var i=0; i<changes.length; i++) {
// 觸發 change:attr 事件
this.trigger('change:' + changes[i], this, current[changes[i]], options);
}
}
if(changing) return this;
if(!silent) {
// 處理遞回change場景
while(this._pending) {
options = this._pending;
this._pending = false;
this.trigger('change', this, options);
}
}
this._pending = false;
this._changing = false;
return this;
}
四、 不足(對比react、vue)
對比現代前端框架,由于Backbone本身比較輕量,對一些內容細節處理不夠細膩,主要體現在:
?視圖和資料的互動關系需要自己分類撰寫邏輯,需要撰寫較多的監聽器
?監聽器數量較大,需要手動銷毀,維護成本較高
?視圖樹的二次渲染僅能實作組件整體替換,并非增量更新,存在性能損失
?路由切換需要自己處理頁面更新邏輯
五、為什么選擇Backbone
看到這里,你可能有些疑問,既然Backbone存在這些缺陷,那么現在學習Backbone還有什么意義呢?
首先,對于服務端開發人員,Backbone底層依賴underscore/lodash、jQuery/Zepto,目前依然有很多基于Jquery和Velocity的專案需要維護,會jQuery就會Backbone,學習成本低;通過Backbone能夠學習用資料去驅動View更新,優化jQuery的寫法;Backbone面對物件編程,符合Java開發習慣,
其次,對于前端開發人員,能夠學習其模塊化封裝庫類函式,提升編程技藝,Backbone的組件化開發,和現代前端框架有很多共通之處,能夠深入理解其演化歷史,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/543198.html
標籤:jQuery
下一篇:返回列表