MVVM框架對比

MVVM框架對比

  • MVC和MVP簡介
  • MVVM
  • Vue.js、Angular.js、Ember、Backbone等框架對比
  • 雙向綁定原理
  • Virtual DOM

前端由於發展比較迅速,框架的更新迭代也比較快,從最初的 backbone.js 到後來的Ember、Knockout、Angular.js, 再到現在的Vue.js、React。

MVC和MVP簡介

mvc通信流程

  • 視圖(view):用戶界面
  • 控制器(controller):業務邏輯
  • 模型(model):數據保存

通信方式如下:

  1. view傳送指令到controller
  2. controller完成業務邏輯後,model改變狀態
  3. model將新的數據發送到view,用戶得到反饋

MVC在前端中的典型實踐 Backbone

backbone通信

MVP

  • MVP模式將controller改名爲Presenter,同時改變了通信方向

mvp模式通信

  1. 各部分之間的通信,都是雙向的。
  2. view與model不發生聯繫,都通過presenter傳遞。
  3. view非常薄,不部署任何業務邏輯,被稱爲被動視圖,所有邏輯都部署在Presenter。

MVVM

mvvm通信

  • 唯一的區別是MVVM採用了雙向數據綁定,view的變動自動反映在view-model。Vue.js、Angular、Ember都採用這種模式;

每一個框架的誕生都是爲了解決客觀存在的問題,所以架構是對客觀不足的妥協。

那麼這麼多MVVM框架的誕生是爲了解決什麼問題?

  • 如何處理數據的更新和界面的更新。

Vue.js、Angular、Ember、Backbone 對比

功能

作爲構建應用的基礎,框架必須具備一些重要的功能,比如,視圖綁定、雙向綁定、篩選、可計算屬性、髒屬性、表單驗證等等

功能 Vue Angular Backbone Ember
可觀察對象(observable) y y y y
路由(routing) y y y y
視圖綁定(view binding) y y - y
雙向綁定(two way binding) y y - y
部分視圖(partial view) y y - y
篩選列表視圖(filtered list view) y y - y
  • 可觀察對象:可以被監聽是否發生變化的對象
  • 路由
  • 視圖綁定:在視圖中使用可觀察對象,讓視圖隨着可觀察對象的變化而自動刷新
  • 雙向綁定
  • 部分視圖:包含其他視圖的視圖
  • 篩選列表視圖:用於顯示根據某些條件篩選出來的對象視圖

靈活性

有時候,框架配合一些現成的插件和庫來使用,可能要比使用框架原生同類功能效果更好,而這種插件和庫幾乎遍地都是(不下數百個),又各有特色。因此,能夠把這些庫和插件整合到MVC框架中也非常重要。

Backbone是其中最靈活的一個框架,因爲它的約定和主張最少。使用Backbone需要你自己作出很多決定。

Ember、Angular、Vue.js 也都還算靈活,可有時候你會發現,就算不喜歡它們的某些實現方法,你也只能默默忍受。 這是在選擇Ember或Angular時必須考慮的。

上手難度

Vue.js
上手比較容易,官方文檔比較清晰。專注於MVVM的ViewModel層,實際的DOM封裝和輸出格式都被抽象爲了Directives和Filters。

Angular 4.0
一開始會讓人大呼過癮,因爲可以利用它幹好多意想不到的事,而且學習難度不高。乍一看讓人覺得很簡單。可是,進了門之後,你會發現後面的路還很長。應該說這個框架比較複雜,而且有不少標新立異之處。想看着它的文檔上手並不現實,因爲Angular製造的概念很多,而文檔中的例子又很少。

Backbone

Backbone的基本概念非常容易理解。但很快你會發現它對怎麼更好地組織代碼並沒有太多主張。爲此,你得觀摩或閱讀一些教程,才能知道在Backbone中怎麼編碼最好。而且,你會發現在有了Backbone的基礎上,還得再找一個庫(比如Marionette或Thorax)跟它配合才能得心應手。正因爲如此,我不認爲Backbone是個容易上手的框架。

Ember

Ember的上手難度與Angular有一拼,我認爲學習Ember比學習Angular總體上容易一些,但它要求你一開始就要先搞懂一批基本概念。而Angular呢,一開始不需要這麼費勁也能做一些讓人興奮不已的事兒。Ember缺少這種前期興奮點。

社區支持

能輕易找到參考資料和專家幫忙嗎?

Backbone的社區很大,這是人所共知的事實。關於Backbone的教程也幾乎汗牛充棟,StackOverflow和IRC社區非常熱鬧。

Angular和Ember社區也相當大,教程什麼的同樣不少,StackOverflow和IRC也很熱鬧,但還是比不上Backbone。

Vue的社區比較一般,可能是由於框架還處於發展階段,還未達到上述幾個框架的穩定和成熟。

有沒有插件或庫構成的生態系統?

Backbone的選擇是最多的,可用插件俯拾皆是,這一點讓其他框架都望塵莫及。Angular的生態圈加上Angular UI還是很令人矚目的。我覺得Ember的下游生態雖然欠發達,但Ember本身很受歡迎, 所以前景十分樂觀。

文件大小

Vue和Angular是唯二不需要其他庫就能使用的,其他幾個框架都需要依賴。
Backbone至少需要 UnderscoreZepto。雖然在Underscore中可以使用最小的模板來渲染視圖,但多數情況下,還要藉助更好的模板引擎,比如 Mustache
Ember 需要 jQueryHandlebars

Vue Angular Backbone Ember
18kb 80kb 61kb 269kb

成熟度

這個框架成熟嗎,經過實際檢驗了嗎,有多少網站在用它呢?

使用Backbone的網站不計其數。最近兩年,它的核心代碼沒怎麼改過,這是成熟的一個重要標誌。

Ember已經不是新框架了,但它的重大變更還是經常有,前幾月剛剛穩定下來。因此,目前還不能說它是個成熟的框架。

Angular似乎比Ember更穩定,驗證的示例也更多,但不能與Backbone相提並論。

Vue 屬於一個新項目,2014-3-20 發佈的0.10.0 Release Candidate版本。

雙向綁定

this.showLoading = false
this.cmsData = data
this.showDownload = data.template.isDownload
this.topBar.displaySharebutton = data.displaySharebutton
this.topBar.title = data.template.title

雙向綁定的基本原理是通過屬性的讀寫器來實現。

function Person() {
var name = ”;
var friends = [];
Object.defineProperty(this, ‘name’, {
get: function () {
console.log(‘get!’)
return name;
},
set: function (value) {
name = value;
friends.push(name)
}
});
this.getFriends = function() {
return friends;
};
}

Virtual DOM

最近一兩年前端最火的技術莫過於ReactJS,即便你沒用過也該聽過,ReactJS由業界頂尖的互聯網公司facebook提出,其本身有很多先進的設計思路,比如頁面UI組件化、虛擬DOM等。

爲什麼需要虛擬DOM?

DOM是很慢的,其元素非常龐大,頁面的性能問題鮮有由JS引起的,大部分都是由DOM操作引起的。如果對前端工作進行抽象的話,主要就是維護狀態和更新視圖;而更新視圖和維護狀態都需要DOM操作。其實近年來,前端的框架主要發展方向就是解放DOM操作的複雜性。

理解虛擬DOM

虛擬的DOM的核心思想是:對複雜的文檔DOM結構,提供一種方便的工具,進行最小化地DOM操作。這句話,也許過於抽象,卻基本概況了虛擬DOM的設計思想。

  1. 提供一種方便的工具,使得開發效率得到保證;
  2. 保證最小化的DOM操作,使得執行效率得到保證;

//設置虛擬dom的相關屬性
var VElement = function(tagName, props, children) {
    //保證只能通過如下方式調用:new VElement
    if (!(this instanceof VElement)) {
        return new VElement(tagName, props, children);
    }

    //可以通過只傳遞tagName和children參數
    if (util.isArray(props)) {
        children = props;
        props = {};
    }
    this.tagName = tagName;
    this.props = props || {};
    this.children = children || [];
    this.key = props ? props.key : void 666;
    var count = 0;
    util.each(this.children, function(child, i) {
        if (child instanceof VElement) {
            count += child.count;
        } else {
            children[i] = '' + child;
        }
        count++;
    });
    this.count = count;
};

通過VElement,我們可以很簡單地用js表示DOM結構。


var vdom = VElement('div', { 'id': 'container' }, [
VElement('h1', { style: 'color:red' }, ['simple virtual dom']),
VElement('p', ['hello world']),
VElement('ul', [VElement('li', ['item #1']), VElement('li', ['item #2'])])
]);

上面的javascript代碼可以表示如下DOM結構:

<div id="container">
<h1 style="color:red">simple virtual dom</h1>
<p>hello world</p>
<ul>
<li>item #1</li>
<li>item #2</li>
</ul>
</div>

比對兩棵DOM樹的差異

DOM樹差異

在用JS對象表示DOM結構後,當頁面狀態發生變化而需要操作DOM時,我們可以先通過虛擬DOM計算出對真實DOM的最小修改量,然後再修改真實DOM結構(因爲真實DOM的操作代價太大)。

  1. 如何比較兩棵DOM樹
    function diff(oldTree, newTree) {
    //節點的遍歷順序
    var index = 0;
    //在遍歷過程中記錄節點的差異
    var patches = {};
    //深度優先遍歷兩棵樹
    dfsWalk(oldTree, newTree, index, patches);
    return patches;
    }
  2. 如何記錄節點之間的差異
  3. 對真實DOM進行最小化修改

針對DOM的處理,可分爲:

  • 修改節點屬性 PROPS
  • 修改節點文本內容 TEXT
  • 替換原有節點 REPLACE
  • 調整子節點,包括移動、刪除 REORDER
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章