MVVM框架設計分析(以vue.js爲例 )

MVVM 框架設計

MVVM 框架已經成爲前端圈的主流,同時也誕生了很多優秀的前端框架,有最早的Angular,以及後起之秀VueReact等,爲我們開發者提供了極大的便利。那麼,什麼樣的框架設計纔算是MVVM框架呢?

MVVM框架的前身

最早使用Java開發的程序員應該瞭解過,當時有一種JSP動態腳本語言,是以JAVA語言作爲載體,由服務端直出HTML網頁的一種技術。下面是JSP的編寫格式:

<html>
<head><title>Hello World</title></head>
<body>
<!-- 語法規則: <% 代碼片段 %> -->
<% out.println("Your IP address is "); %> 

<br/>

<% out.println(request.getRemoteAddr()); %>
</body>
</html>

頁面結果輸出爲: Your IP address is: xx.xx.xx.xx

可以看到這種腳本語言的一些特點:

  • 高耦合 (視圖界面和功能邏輯互相糅合)
  • 複用性差
  • SEO相對較好 (服務端直出)

什麼是MVVM

MVVM是一種程序設計框架。拆分出來就是:M-V-VM

  • M: Modal(數據模型層)
  • V: View (視圖界面層)
  • VM: ViewModal(視圖模型層)

下圖是一個Vue框架的結構:

在這裏插入圖片描述
可以看出:

  • 視圖(View)通過事件綁定影響數據模型(Modal)
  • 數據模型通過數據驅動渲染視圖
  • 視圖層數據模型層是相互獨立的,通過視圖模型進行關聯

這種通過ViewModal相互影響的過程就是MVVM最大的特性(雙向綁定)

數據驅動視圖

作者認爲,MVVM最大的特點就是它。無須操作DOM,只需修改數據,即可影響視圖。

因爲在這個框架出現之前,前端一直都是通過直接操作DOM,來影響視圖的。這樣做最大的弊端就是頻繁操作DOM,會導致處理繁瑣、代碼冗餘,而且如果DOM操作不當就會導致頁面渲染性能下降。瀏覽器重繪和迴流

比如實現場景:在input中輸入某個值,對應顯示在一個div中。我們就需要監聽input值的變化,然後寫入到對應的div中。

<script type="text/JavaScript">
function valChange(e){
	document.querySelector('#app').innerHTML =  e.target.value
}
</script>

<input type="text" id="a" oninput="valChange(event)" onporpertychange="valChange(event)" />
<div id="app"></div>

這種寫法有一個最大的缺點就是視圖層和我們的業務邏輯還是有糅合,如果需要最大化解耦,看看Vue如何去實現的:

<template>
<div>
	<!-- 視圖模板 -->
	<input type="text" v-model="userName">
	<div>{{userName}}</div>
</div>

<script>
export default {
	data:{
		return {
			userName: '' // 數據模型
		}
	}
}
</script>
</template>

可以看到,當v-modal綁定的值發生改變時,頁面會自動渲染更新對應的值。我們只需要聲明視圖模板,並且綁定對應的數據模型,那麼我們的視圖層就再也無需過多關心,這極大提升前端開發的工作效率。

點擊此處進行測試

MVVM 的特點

1. 數據綁定

M-V-VM框架核心就是數據綁定,將ViewModal進行關聯。數據綁定實現的關鍵就是指令,指令的職責是當表達式的值改變時,將其產生的連帶影響,響應式地作用於 DOM。因此,操作DOM相關的邏輯也是封裝在指令中實現。參考 Vue.js 指令

在這裏插入圖片描述

Vue.js提供了指令機制: 用戶可以通過具有特殊前綴的HTML 屬性(v-htmlv-text等)來實現數據綁定,也可以使用常見的花括號({{}})模板插值,或是在表單元素上使用雙向綁定(v-model)。

Vue會給動態更新的DOM節點創建對應的指令對象,當觀測到指令對象的值發生變化時,它所綁定的目標節點就會執行對應的DOM操作。

2. 數據觀測(監聽)

數據觀測(監聽)的實現方式不同框架有不同的實現方式:一種是像Ng提出的髒檢查(dirty checking) 機制,而Vue採用的是基於依賴收集的觀測機制。此處重點講解Vue的實現原理:

在這裏插入圖片描述

  • 數據劫持,將原生js對象改造成可觀測對象
    實現手段有兩種: ES5的Object.defineProperty方法以及ES6的Proxy方式(數據劫持實現原理)
  • 註冊訂閱者watcher求值過程中,每一個被取值的數據對象,都會將當前作用域的watcher作爲自己的訂閱者(寫入到setter中),併成爲當前watcher的一個依賴
  • 觸發更新 當被依賴的數據對象進行賦值操作時,它會通知自己的watcher重新求值,並觸發更新

概念

  1. watcher:用來觀測數據的對象,叫做watcher
  2. 依賴收集: 通過重寫getter、setter,將數據的依賴關係明確化,這樣可以加快數據觀察和更新的效率。
  3. 訂閱者(dep): vueDep對象就是一種發佈訂閱者模式,訂閱就是將watcher push到數組,發佈就是將數組中的函數執行並popvue/dep.js實現源碼

3.虛擬DOM

虛擬DOM就是爲了解決瀏覽器性能問題(頻繁操作DOM)而被設計出來的。頁面性能大部分的性能瓶頸都在操作DOM上,而JS引起頁面卡頓的很少有,如果有10個div節點依次插入到body中,每插入一個div都會導致頁面重繪,可以想象如果有1000條數據同時加載,這樣會嚴重影響用戶體驗。因此,Virtual DOM就是爲了解決這個問題被設計出來的。

虛擬的DOM的核心思想是:對複雜的文檔DOM結構,提供一種方便的實現,進行最小化地DOM操作。

4.組件

Vue.js的組件可以理解爲預先定義好了行爲的ViewModel類,例如vue.js比較流行的組件庫(iVew)。

組件爲開發者提供了可複用、可擴展的特徵。vuejs 組件

組件的核心

  • 模板(template)
  • 數據(data)
  • 外部參數(props)
  • 方法(methods)
  • 鉤子函數(hook function)

後記

本文只是簡單的介紹了MVVM的設計思想,以及社區實現的項目。每個具體框架實現的細節這裏也沒有過多的展開,比如diff算法實現原理、模板編譯相關,相關源碼分析等。後續將會逐一展開進行討論。

參考文檔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章