摘要:下面我們會向大家解釋清楚為什么這個這么重要,以及它和的響應(yīng)式數(shù)據(jù)流有什么關(guān)系。源碼前面鋪墊這么多就是希望大家能理解接下來要講的響應(yīng)式數(shù)據(jù)流。總結(jié)講到這里大家應(yīng)該都能夠明白的響應(yīng)式數(shù)據(jù)流是如何實現(xiàn)的。
Vue、React介紹
目前前端社區(qū)比較推崇的框架有Vue 和 React,公司內(nèi)部許多端都自發(fā)的將原有的老技術(shù)方案(widget + jQuery)遷移到 Vue / React上了。
我覺得Vue / React 有以下幾點優(yōu)勢
首先它們都有完整的組件化方案
virtual Dom (前端性能提升利器)
成熟的社區(qū)生態(tài)
介紹一個Vue例子上面的例子我們初始化了一個vue組件,當我們改變這個組件的狀態(tài)時,頁面的內(nèi)容也會隨之改變,這中間并不需要我們手動的去操作頁面上的dom元素。
同時我們注意到Vue提供了一個語法糖 ——watch,這個就是我們今天要講的 Vue響應(yīng)式數(shù)據(jù)流的主角!代碼很簡單,就是組件的狀態(tài) name 改變的時候我們輸出一句話 “name change”。
下面我們會向大家解釋清楚為什么這個 watch 這么重要,以及它和 Vue的響應(yīng)式數(shù)據(jù)流有什么關(guān)系。
Vue 和 React 都是前端的組件化框架,功能上大同小異,本質(zhì)上就是借助virtual Dom幫助開發(fā)者管理混亂的Dom,并提供給開發(fā)者像操作狀態(tài)機一樣操作頁面的能力。
但是Vue的virtual Dom 不是普通的 virtual Dom
Vue 2.0 的實現(xiàn)有與眾不同的地方。和 Vue 的響應(yīng)式系統(tǒng)結(jié)合在一起之后,它可以讓你不必做任何事就獲得完全優(yōu)化的重渲染。由于每個組件都會在渲染時追蹤其響應(yīng)依賴,所以系統(tǒng)精確地知道應(yīng)該何時重渲染、應(yīng)該重渲染哪些組件。不需要 shouldComponentUpdate,也不需要 immutable 數(shù)據(jù) - it just works . —— 尤雨溪
我們看一下第三方的性能分析:
除了性能,最大的優(yōu)勢是減輕了開發(fā)者的負擔,開發(fā)者大多數(shù)情況下不需要依賴 shouldComponentUpdate,也不需要依賴 immutable 數(shù)據(jù)去判斷組件是否需要重新渲染,Vue會幫你做好這件事。
舉個例子來說明這兩個的virtual dom的不同之處:
預(yù)備知識:Object.defineProperty 與 訂閱發(fā)布設(shè)計模式 Object.defineProperty開發(fā)者就像一個老師,Vue和React這兩個學生要做的事就是根據(jù)老師給出的長寬畫出對應(yīng)的長方形。每當老師改變給出的長和寬時,Vue能夠自己發(fā)現(xiàn)長和寬變沒變,需不需要重新畫;React則需要老師告訴它長和寬變了,需要重新畫了。
JavaScript 提供一個非常強大的方法 Object.defineProperty,它可以定義當某一個值訪問和賦值時會先執(zhí)行自定義的鉤子方法。
一個簡單的Object.defineProperty例子var obj = {}; var initValue = "hello"; Object.defineProperty(obj,"newKey",{ get:function (){ //當獲取值的時候觸發(fā)的函數(shù) return initValue; }, set:function (value){ //當設(shè)置值的時候觸發(fā)的函數(shù),設(shè)置的新值通過參數(shù)value拿到 console.log(value) initValue = value; } }); //獲取值 console.log( obj.newKey ); //hello //設(shè)置值 obj.newKey = "change value"; //change value
這個方法給予JavaScript開發(fā)一種面向切面編程的能力,使用該方法我們能夠隱式、自然的控制屬性的訪問和賦值。
訂閱發(fā)布設(shè)計模式訂閱發(fā)布是一個非常常見的設(shè)計模式,原理也非常簡單就是訂閱者訂閱信息,然后發(fā)布者發(fā)布信息通知訂閱者更新。
Vue 源碼前面鋪墊這么多就是希望大家能理解接下來要講的響應(yīng)式數(shù)據(jù)流。
Vue的初始化
如上圖,Vue的初始化會執(zhí)行一系列的方法,這里我們主要介紹Vue的initState 方法。
prop和data都是組件的屬性,prop通常上是父組件傳遞下來的,data是組件自身定義的,Vue不推薦你去改組件傳遞下來的prop,因為那樣會帶來不必要的復(fù)雜度。
Prop和data 的最終歸宿都是遞歸執(zhí)行 defineReactive方法。
那defineReactive方法做了什么呢?
defineReactive會用 Object.defineProperty將組件的每個屬性都包裝一下,這樣誰訪問了這些屬性,誰重新賦值了這些屬性我們都能追蹤到了。
Vue里面有一個 Observe類,所有的prop子屬性和data本身都會帶有一個Observer對象,Observer的構(gòu)造函數(shù)
在控制臺我們可以看到每個屬性下都有__ob__,這說明這個屬性已經(jīng)被包裝成 Observer對象了,所以的訪問和賦值都能給追蹤到,這里面也保存著所有訂閱該Observer的訂閱者Watcher。
我們看一下Watcher的構(gòu)造函數(shù)
Watcher支持 watch 一個表達式或者是一個方法。Watcher在構(gòu)造的時候會先獲取一次expOrFn的值,下面我們把expOrFn稱為Watcher的Getter。
Dep還有一個關(guān)鍵的類是Dep,這個類會幫助我們的屬性記錄下所有的Watcher,每個屬性都有自己的Dep實例,同時Vue的Watcher訪問的屬性的時候 Dep會作為一個全局變量將自身的target屬性指向訪問的Wathcer。會執(zhí)行下面的方法
同時我們再回來看 defineReactive這個重要的方法
當Watcher訪問組件的屬性時,通過Dep.target,Vue可以知道是Watcher訪問的, 這樣當Vue自己的Watcher訪問屬性的時候會被記錄成訂閱者,而我們訪問的時候Vue不會執(zhí)行多余的代碼。這是一個很精妙的設(shè)計,將Object.defineProperty 與 訂閱發(fā)布設(shè)計模式結(jié)合起來了。
看一下整個的流程圖
理解了以上Vue是如何將Object.defineProperty 與 訂閱發(fā)布設(shè)計模式結(jié)合起來的,然后我們再舉一反三:Vue的render函數(shù)如果就是 Watcher 的 expOrFn會怎么樣?
回到Vue的源碼里:
這里的 vm._render就是 render函數(shù)的一個封裝,我們可以看到本質(zhì)上:Vue的render函數(shù)就是 Watcher 的 expOrFn。那初始化的時候我們會先執(zhí)行一邊 render函數(shù),在執(zhí)行render函數(shù)的過程中訪問了哪些 組件的屬性,Vue都會用上面的提到的方法幫我們把依賴記錄下來。所以當這個屬性變化的時候,自然而然,就像文章開頭的watch一樣,我們會重新render一次,(開頭的例子是輸出“name change”)。
總結(jié)講到這里大家應(yīng)該都能夠明白Vue的響應(yīng)式數(shù)據(jù)流是如何實現(xiàn)的。同時我們能夠發(fā)現(xiàn)Vue提供給我們的許多語法糖都是同樣的道理,比如Vue的computer就是將computer函數(shù)作為Watcher的expOrFn。
希望大家在理解Vue響應(yīng)式數(shù)據(jù)流的基礎(chǔ)上能夠更加自信、靈活和穩(wěn)健的使用這個優(yōu)秀的框架。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/81040.html
摘要:在看的實現(xiàn)之前。實現(xiàn)響應(yīng)式的關(guān)鍵有三個遍歷中的屬性。在方法中設(shè)置核心數(shù)據(jù)劫持每個屬性都有一個自己的消息訂閱起用于訂制該屬性上的所有觀察者觀察者,通過實現(xiàn)對響應(yīng)屬性的監(jiān)聽觀察。觀察得到結(jié)果后,主動觸發(fā)自己的回調(diào)可以去看看的這三部分源碼。 本來vue的響應(yīng)式應(yīng)該才是重中之重。但是網(wǎng)上的文章很多很多。在看computed的實現(xiàn)之前。肯定還是要把vue的響應(yīng)式如何實現(xiàn)好好看一下。或者說兩者根本...
寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學習吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關(guān)注公眾號也可以吧 【Vue原理】Props - 源碼版 今天記錄 Props 源碼流程,哎,這東西,就算是研究過了,也真是會隨著時間慢慢忘記的。 幸好我做...
摘要:先說遍歷,很簡單,如下行左右代碼就足夠遍歷一個對象了遇到普通數(shù)據(jù)屬性,直接處理,遇到對象,遍歷屬性之后遞歸進去處理屬性,遇到數(shù)組,遞歸進去處理數(shù)組元素。這樣改進之后我就不需要對數(shù)組元素進行響應(yīng)式處理,只是遇到數(shù)組的時候把數(shù)組的方法變異即可。 用了Vue很久了,最近決定系統(tǒng)性的看看Vue的源碼,相信看源碼的同學不在少數(shù),但是看的時候卻發(fā)現(xiàn)挺有難度,Vue雖然足夠精簡,但是怎么說現(xiàn)在也有1...
摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學習吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關(guān)注公眾號也可以吧如果你覺得排版難看,請點擊下面公眾號 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學習吧研究基...
摘要:當東西發(fā)售時,就會打你的電話通知你,讓你來領(lǐng)取完成更新。其中涉及的幾個步驟,按上面的例子來轉(zhuǎn)化一下你買東西,就是你要使用數(shù)據(jù)你把電話給老板,電話就是你的,用于通知老板記下電話在電話本,就是把保存在中。剩下的步驟屬于依賴更新 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學習吧研究基于 Vue版本 【...
閱讀 3212·2021-11-02 14:44
閱讀 3725·2021-09-02 15:41
閱讀 1661·2019-08-29 16:57
閱讀 1784·2019-08-26 13:38
閱讀 3297·2019-08-23 18:13
閱讀 2104·2019-08-23 15:41
閱讀 1668·2019-08-23 14:24
閱讀 3029·2019-08-23 14:03