重溫vue.js---核心概念

Vue.js : 是一套構建用戶界面的漸進式框架。

一、什么是框架?

在最初前端開發中,為了完成某個任務,我們首先利用js從html文件中獲取dom元素,隨后添加事件,最后進行一系列的js編程操作,這種開發方式暫且稱為“don流”,在現實開發中需求變化,復雜的業務邏輯和巨大的代碼量是“dom流”無法承受的,

對應以上問題,衍變出了把js代碼劃分為三個板塊:數據,視圖,邏輯控制,數據版塊只含有數據內容,視圖板塊只負責更改樣式,邏輯控制負責聯系視圖板塊和數據版塊和相應的邏輯。這樣代碼結構變得清晰易懂,因需求而改動代碼程度變小。

其實這種開發方式,就是我們常說的MV模式,而MVC、MVVM、 MVP[2]等都是MV的衍生物

而這種MV*的代碼組織方式,漸漸的就演變成了所謂的框架。

Vue的核心定位并不是一個框架,設計上也沒有完全遵循MVVM模式,可以看到在圖中只有State和View兩部分, Vue的核心功能強調的是狀態到界面的映射,對于代碼的結構組織并不重視, 所以單純只使用其核心功能時,它并不是一個框架,而更像一個視圖模板引擎,這也是為什么Vue開發者把其命名成讀音類似于view的原因。

image

二、對漸進式的理解:

如下圖所示,這里包含了Vue的所有部件,在聲明式渲染(視圖模板引擎)的基礎上,我們可以通過添加組件系統、客戶端路由、大規模狀態管理來構建一個完整的框架。更重要的是,這些功能相互獨立,你可以在核心功能的基礎上任意選用其他的部件,不一定要全部整合在一起。可以看到,所說的“漸進式”,其實就是Vue的使用方式,同時也體現了Vue的設計的理念

image

以上參考http://blog.csdn.net/crazy_banana/article/details/71079925

Vue.js是一個提供MVVM數據雙向綁定的庫,專注于UI層面,核心思想是:數據驅動、組件系統。

三、核心內容

【1】、Vue渲染邏輯

===============Render函數===============

$mount方法就是整個渲染過程的起始點

在渲染過程中,提供了三種渲染模式,自定義Render函數、template、el均可以渲染頁面,也就是對應我們使用Vue時,三種寫法:

2、3這兩種都屬于聲明式渲染

1. 自定義Render函數
1.Vue.component('anchored-heading', {
2.    render: function (createElement) {
3.        return createElement(
4.            'h' + this.level,   // tag name 標簽名稱
5.            this.$slots.default // 子組件中的陣列
6.        )
7.    },
8.    props: {
9.        level: {
10.            type: Number,
11.            required: true
12.        }
13.    }
14.})
2. template寫法
1.var vm = new Vue({
2.    data: {
3.        // 以一個空值聲明 `msg`
4.        msg: ''
5.    },
6.    template: '<div>{{msg}}</div>'
7.})
3. el寫法(這個就是入門時最基本的寫法)
1.var app = new Vue({
2.    el: '#app',
3.    data: {
4.        message: 'Hello Vue!'
5.    }
6.})

這三種渲染模式最終都是要得到Render函數。只不過用戶自定義的Render函數省去了程序分析的過程,等同于處理過的Render函數,而普通的template或者el只是字符串,需要解析成AST,再將AST轉化為Render函數。

===============虛擬DOM&patch方法===============

Virtual DOM有多種實現方式,但基本思路都是一樣的,分為兩步:

1.Render函數生成Virtual DOM
VNode對象是什么?

VNode就是Vue.js 2.0中的Virtual DOM,在Vue.js 2.0中,相較Vue.js 1.0引入了Virtual DOM的概念
在Vue.js 2.0中Javascript模擬DOM模型樹就是VNode,Render函數執行后都會返回VNode對象,為下一步操作做準備。

2.Virtual DOM通過DOM Diff算法查找差異,將差異轉為真正DOM節點

Render函數執行生成了VNode,而VNode只是Virtual DOM,我們還需要通過DOM Diff之后,來生成真正的DOM節點。在Vue.js 2.0中,是通過/src/core/vdom/patch.js中的patch(oldVnode, vnode ,hydrating)方法來完成的。

其主要邏輯為當VNode為真實元素或舊的VNode和新的VNode完全相同時,直接調用createElm方法生成真實的DOM樹,當VNode新舊存在差異時,則調用patchVnode方法,通過比較新舊VNode節點,根據不同的狀態對DOM做合理的添加、刪除、修改DOM(這里的Diff算法有興趣的讀者可以自行閱讀patchVnode方法,鑒于篇幅不再贅述),再調用createElm生成真實的DOM樹。

===============Watcher & 數據驅動 & 依賴追蹤===============


image.png
2、什么是數據驅動

數據驅動是vuejs最大的特點。在vuejs中,所謂的數據驅動就是當數據發生變化的時候,用戶界面發生相應的變化,開發者不需要手動的去修改dom。

vuejs是如何實現這種數據驅動的呢?

Vuejs的數據驅動是通過MVVM這種框架來實現的。MVVM框架主要包含3個部分:model、view和 viewmodel。

Model:指的是數據部分,對應到前端就是javascript對象

View:指的是視圖部分,對應前端就是dom

Viewmodel:就是連接視圖與數據的中間件

image

數據(Model)和視圖(View)是不能直接通訊的,而是需要通過ViewModel來實現雙方的通訊。當數據變化的時候,viewModel能夠監聽到這種變化,并及時的通知view做出修改。同樣的,當頁面有事件觸發時,viewMOdel也能夠監聽到事件,并通知model進行響應。Viewmodel就相當于一個觀察者,監控著雙方的動作,并及時通知對方進行相應的操作。

vuejs是通過在實現一個觀察者來實現的數據驅動。
image.png
如何實現數據驅動的?

首先,vuejs在實例化的過程中,會對遍歷傳給實例化對象選項中的data 選項,遍歷其所有屬性并使用 Object.defineProperty 把這些屬性全部轉為 getter/setter。

同時每一個實例對象都有一個watcher實例對象,他會在模板編譯的過程中,用getter去訪問data的屬性,watcher此時就會把用到的data屬性記為依賴,這樣就建立了視圖與數據之間的聯系。當之后我們渲染視圖的數據依賴發生改變(即數據的setter被調用)的時候,watcher會對比前后兩個的數值是否發生變化,然后確定是否通知視圖進行重新渲染。

這樣就實現了所謂的數據對于視圖的驅動。

3、vue響應式原理---依賴追蹤
Vue的依賴追蹤通過ES5的 Object.defineProperty 方法實現。

比如,我們給它一個原生對象,Vue會遍歷這個數據對象的屬性,然后進行屬性轉換。每一個屬性會被轉換為一個 getter 和一個 setter。同時每個組件會有一個對應的 watcher 對象,這個對象的職責就是在當前組件被渲染的時候,記錄數據上面的哪些屬性被用到了。

例如,在渲染函數里面用到A.B的時候,這個就會觸發對應的 getter。整個渲染流程具體要點如下:

當某個數據屬性被用到時,觸發 getter,這個屬性就會被作為依賴被 watcher 記錄下來。

整個函數被渲染完的時候,每一個被用到的數據屬性都會被記錄。

相應的數據變動時,例如給它一個新的值,就會觸發 setter,通知數據對象對應數據有變化。

此時會通知對應的組件,其數據依賴有所改動,需要重新渲染。

對應的組件再次調動渲染函數,生成 Virtual DOM,實現 DOM 更新。

在Vue里面由于依賴追蹤系統的存在,當任意數據變動的時,Vue的每一個組件都精確地知道自己是否需要重繪,所以并不需要手動優化。用Vue渲染這些組件的時候,數據變了,對應的組件基本上去除了手動優化的必要性。

核心關鍵的幾步流程還是非常清晰的:

1、new Vue,執行初始化
2、掛載$mount方法,通過自定義Render方法、template、el等生成Render函數
3、通過Watcher監聽數據的變化
4、當數據發生變化時,Render函數執行生成VNode對象
5、通過patch方法,對比新舊VNode對象,通過DOM Diff算法,添加、修改、刪除真正的DOM元素
至此,整個new Vue的渲染過程完畢。

render流程:

1、創建虛擬DOM
2、真實DOM 連接 虛擬DOM
3、視圖更新
4、計算 [ 新虛擬DOM ] 和 [ 舊虛擬DOM ] 的差異 ( diff )
5、根據計算的 差異, 更新真實DOM ( patch )
這里牽涉到兩個詞語 diff 和 patch,稍后再解釋,這里簡單理解為 [計算差異]和[應用差異]。

【2】、組件系統

核心思想都是一樣,把UI結構映射到恰當的組件樹

image.png

在Vue中,父子組件之間的通信是通過 props 傳遞。從父向子單向傳遞;而如果子組件想要在父組件作用里面產生副作用,就需要去派發事件。這樣就形成一個基本的父子通信模式,在涉及大規模狀態管理的時候會有額外的方案,這個后面會提到。

image.png
組件+構建工具==> 單文件組件概念

在同一個Vue文件里,可以同時寫 template, script 和 style,三個東西放在一個里面。這樣的好處是有了一個構建的機會,可以對這些單文件組件做更多的分析處,在每一個語言塊里可以單獨使用不同的處理器

以上參考
http://blog.csdn.net/generon/article/details/72482844
https://www.cnblogs.com/caizhenbo/p/6418284.html
https://www.tuicool.com/articles/6nEjAjb
https://cn.vuejs.org/v2/guide/reactivity.html

生命周期
生命周期.png
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容