Backbone前端框架核心及源碼解析
一、 什么是Backbone
在前端的發(fā)展道路中,前端框架元老之一jQuery對繁瑣的DOM操作進行了封裝,提供了鏈式調用、各類選擇器,屏蔽了不同瀏覽器寫法的差異性,但是前端開發(fā)過程中依然存在作用域污染、代碼復用度低、冗余度高、數據和事件綁定煩瑣等痛點。
5年后,Backbone橫空出世,通過與Underscore、Require、Handlebar的整合,提供了一個輕量和友好的前端開發(fā)解決方案,其諸多設計思想對于后續(xù)的現代化前端框架發(fā)展起到了舉足輕重的作用,堪稱現代前端框架的基石。
通過對Backbone前端框架的學習,讓我們領略其獨特的設計思想。
二、 核心架構
按照MVC框架的定義,MVC是用來將應用程序分為三個主要邏輯組件的架構模式:模型,視圖和控制器。這些組件被用來處理一個面向應用的特定開發(fā)。 MVC是最常用的行業(yè)標準的Web開發(fā)框架,以創(chuàng)建可擴展的項目之一。 Backbone.js為復雜WEB應用程序提供模型(models)、集合(collections)、視圖(views)的結構。
? 其中模型用于綁定鍵值數據,并通過RESRful JSON接口連接到應用程序;
? 視圖用于UI界面渲染,可以聲明自定義事件,通過監(jiān)聽模型和集合的變化執(zhí)行相應的回調(如執(zhí)行渲染)。
如圖所示,當用戶與視圖層產生交互時,控制層監(jiān)聽變化,負責與數據層進行數據交互,觸發(fā)數據Change事件,從而通知視圖層重新渲染,以實現UI界面更新。更進一步,當數據層發(fā)生變化時,由Backbone提供了數據層和服務器數據共享同步的能力。
其設計思想主要包含以下幾點:
?數據綁定(依賴渲染模板引擎)、事件驅動(依賴Events)
?視圖組件化,并且組件有了生命周期的概念
?前端路由配置化,實現頁面局部刷新
這些創(chuàng)新的思想,在現代前端框架中進一步得到了繼承和發(fā)揚。
三、 部分源碼解析
Backbone極度輕量,編譯后僅有幾kb,貫穿其中的是大量的設計模式:工廠模式、觀察者模式、迭代器模式、適配器模式……,代碼流暢、實現過程比較優(yōu)雅。按照功能拆分為了Events、Model、Collection、Router、History、View等若干模塊,這里摘取了部分精彩源碼進行了解析,相信對我們的日常代碼開發(fā)也有一定指導作用:
(1)迭代器
EventsApi起到一個迭代器分流的作用,對多個事件進行解析拆分,設計的非常經典,執(zhí)行時以下用法都是合法的:
?用法一:傳入一個名稱和回調函數的對象
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)監(jiān)聽器
用于一個對象監(jiān)聽另外一個對象的事件,例如,在A對象上監(jiān)聽在B對象上發(fā)生的事件,并且執(zhí)行A的回調函數:
A.listenTo(B, "b", callback)
實際上這個功能用B對象來監(jiān)聽也可以實現:
B.on("b", callback, A)
這么做的好處是,方便對A創(chuàng)建、銷毀邏輯的代碼聚合,并且對B的侵入程度較小。實現如下:
Events.listenTo = function(obj, name, callback) { if(!obj) return this; var id = obj._listenId || (obj._listenId = _.uniqueId('l')); // 當前對象的所有監(jiān)聽對象 var listeningTo = this._listeningTo || (this._listeningTo = {}); var listening = listeningTo[id]; if(!listening) { // 創(chuàng)建自身監(jiān)聽id var thisId = this._listenId || (this._listenId = _.uniqueId('l')); listening = listeningTo[id] = {obj: obj, objId: id, id: thisId, listeningTo: listeningTo, count: 0}; } // 執(zhí)行對象綁定 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) { // 存儲變更前的狀態(tài)快照 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++) { // 觸發(fā) 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本身比較輕量,對一些內容細節(jié)處理不夠細膩,主要體現在:
?視圖和數據的交互關系需要自己分類編寫邏輯,需要編寫較多的監(jiān)聽器
?監(jiān)聽器數量較大,需要手動銷毀,維護成本較高
?視圖樹的二次渲染僅能實現組件整體替換,并非增量更新,存在性能損失
?路由切換需要自己處理頁面更新邏輯
五、為什么選擇Backbone
看到這里,你可能有些疑問,既然Backbone存在這些缺陷,那么現在學習Backbone還有什么意義呢?
首先,對于服務端開發(fā)人員,Backbone底層依賴underscore/lodash、jQuery/Zepto,目前依然有很多基于Jquery和Velocity的項目需要維護,會jQuery就會Backbone,學習成本低;通過Backbone能夠學習用數據去驅動View更新,優(yōu)化jQuery的寫法;Backbone面對對象編程,符合Java開發(fā)習慣。
其次,對于前端開發(fā)人員,能夠學習其模塊化封裝庫類函數,提升編程技藝。Backbone的組件化開發(fā),和現代前端框架有很多共通之處,能夠深入理解其演化歷史。
以上就是Backbone前端框架核心及源碼解析的詳細內容,更多關于Backbone前端框架的資料請關注腳本之家其它相關文章!
相關文章
vue3的介紹和兩種創(chuàng)建方式詳解(cli和vite)
這篇文章主要介紹了vue3的介紹和兩種創(chuàng)建方式(cli和vite),vue3對比vue2帶來的性能提升有很多優(yōu)勢,總體來說Vue 3在性能、開發(fā)體驗和代碼組織方面都有所改進,使得它更加適合于大型、復雜的應用程序開發(fā),需要的朋友可以參考下2023-04-04vue表單驗證rules及validator驗證器的使用方法實例
在vue開發(fā)中,難免遇到各種表單校驗,下面這篇文章主要給大家介紹了關于vue表單驗證rules及validator驗證器使用的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下2022-07-07Vue3全局屬性app.config.globalProperties的實現
Vue3中的app.config.globalProperties是一個強大的全局配置功能,允許我們在應用級別設置和訪問屬性,本文主要介紹了Vue3全局屬性app.config.globalProperties的實現,具有一定的參考價值,感興趣的可以了解一下2024-01-01