摘要:其成員函數(shù)最主要的是和,前者用來設置某個的依賴,后者則用來通知與這個依賴相關的來運行其回調函數(shù)。也就是進行數(shù)據(jù)更新操作。
vue框架的兩個抽象核心:虛擬DOM和相應式數(shù)據(jù)原理
關于虛擬DOM的核心算法,我們上一章已經基本解析過了,詳細的見
React && VUE Virtual Dom的Diff算法統(tǒng)一之路 snabbdom.js解讀
關于響應式數(shù)據(jù)原理,我們先看張圖
你 ‘ (4).png
具體來講,要分以下幾步:
初始化實例對象時運行initState, 建立好props, data 的鉤子以及其對象成員的Observer, 對于computed 屬性,則建立起所有對應的 Watcher 并且通過 Object.defineProperty 在vm對象上設置一個該屬性的 getter。同時還根據(jù)自定義的 watch 來建立相應的 Watcher
執(zhí)行掛載操作,在掛載時建立一個直接對應render(渲染)的 Watcher,并且編譯模板生成 render 函數(shù),執(zhí)行vm._update 來更新 DOM 。
此后每當有數(shù)據(jù)改變,都將通知相應的 Watcher 執(zhí)行回調函數(shù)。
Observer 劫持者export class Observer { value: any; dep: Dep; vmCount: number; // number of vms that has this object as root $data constructor (value: any) { this.value = value this.dep = new Dep() this.vmCount = 0 def(value, "__ob__", this) if (Array.isArray(value)) { const augment = hasProto ? protoAugment : copyAugment augment(value, arrayMethods, arrayKeys) this.observeArray(value) } else { this.walk(value) } } /** * Walk through each property and convert them into * getter/setters. This method should only be called when * value type is Object. */ walk (obj: Object) { const keys = Object.keys(obj) for (let i = 0; i < keys.length; i++) { defineReactive(obj, keys[i], obj[keys[i]]) } } /** * Observe a list of Array items. */ observeArray (items: Array) { for (let i = 0, l = items.length; i < l; i++) { observe(items[i]) } } }
首先我們觀察到,new Observer()的時候,會進行類型的判斷
if (Array.isArray(value)) { const augment = hasProto ? protoAugment : copyAugment augment(value, arrayMethods, arrayKeys) this.observeArray(value) } else { this.walk(value) }
如果是數(shù)組類型則會遞歸調用,建立依賴體系
否則則調用walk()函數(shù)去利用Object.defineProperty簡歷依賴
那么defineReactive是如何實現(xiàn)的呢,如下
//省略了部分代碼 export function defineReactive ( obj: Object, key: string, val: any, customSetter?: ?Function, shallow?: boolean ) { const dep = new Dep() ... Object.defineProperty(obj, key, { ... get: function reactiveGetter () { ... dep.depend() ... return value }, set: function reactiveSetter (newVal) { ... dep.notify() } }) }
攔截器會分別在getter和setter上設置中間件去維護dep數(shù)組中的依賴關系
dep.depend()
dep.notify()
字面意思非常明顯,分別用于增加依賴和通知依賴變化關系
Dep (dependency // 依賴)class Dep { static target: ?Watcher; id: number; subs: Array; constructor () { this.id = uid++ this.subs = [] } addSub (sub: Watcher) { this.subs.push(sub) } removeSub (sub: Watcher) { remove(this.subs, sub) } depend () { if (Dep.target) { Dep.target.addDep(this) } } notify () { // stabilize the subscriber list first const subs = this.subs.slice() for (let i = 0, l = subs.length; i < l; i++) { subs[i].update() } } }
Dep 就是一個 Watcher 所對應的數(shù)據(jù)依賴,在這個對象中也存有一個 subs 數(shù)組,用來保存和這個依賴有關的 Watcher。其成員函數(shù)最主要的是 depend 和 notify ,前者用來設置某個 Watcher 的依賴,后者則用來通知與這個依賴相關的 Watcher 來運行其回調函數(shù)。
我們知道,Dom 上通過指令或者雙大括號綁定的數(shù)據(jù),會為數(shù)據(jù)進行添加觀察者watcher,當實例化Watcher的時候 會觸發(fā)屬性的getter方法,此時會調用dep.depend()。我們看一下depend方法:
depend () { if (Dep.target) { Dep.target.addDep(this) } }
Dep.target 是什么東西呢?其實在進行Watcher實例化的時候,會調用內部的get函數(shù),開始為他初始化
Watcher 觀察者其中pushTarget 方法就是為Dep.target綁定此watcher實例,所以Dep.target.addDep(this)也就是執(zhí)行此實例中的addDep方法
addDep (dep: Dep) { ... dep.addSub(this) }
這樣便為我們的dep實例添加了一個watcher實例。
接著當我們更新data的時候,會觸發(fā)他的set方法,執(zhí)行dep.notify()函數(shù):
notify () { // stabilize the subscriber list first const subs = this.subs.slice() for (let i = 0, l = subs.length; i < l; i++) { subs[i].update() } }
這里也就是遍歷dep中收集到的watcher實例,進行update()。也就是進行數(shù)據(jù)更新操作。這也就是簡單的數(shù)據(jù)響應式,其實還需要注意的是: 當數(shù)據(jù)的getter觸發(fā)后,會收集依賴,但也不是所有的觸發(fā)方式都會收集依賴,只有通過watcher觸發(fā)的getter會收集依賴:if (Dep.target) { dep.depend() },而所謂的被收集的依賴就是當前watcher,DOM中的數(shù)據(jù)必須通過watcher來綁定,只通過watcher來讀取。
最后付一個函數(shù)timeline
的.png
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102995.html
摘要:下面我們會向大家解釋清楚為什么這個這么重要,以及它和的響應式數(shù)據(jù)流有什么關系。源碼前面鋪墊這么多就是希望大家能理解接下來要講的響應式數(shù)據(jù)流。總結講到這里大家應該都能夠明白的響應式數(shù)據(jù)流是如何實現(xiàn)的。 Vue、React介紹 目前前端社區(qū)比較推崇的框架有Vue 和 React,公司內部許多端都自發(fā)的將原有的老技術方案(widget + jQuery)遷移到 Vue / React上了。我...
摘要:今天,就我們就來一步步解析響應式的原理,并且來實現(xiàn)一個簡單的。當然,這個也只是一個簡單的,來說明響應式的原理,真實的源碼會更加復雜,因為加了很多其他邏輯。接下來我可能會將其與聯(lián)系起來,實現(xiàn)和語法。 從很久之前就已經接觸過了angularjs了,當時就已經了解到,angularjs是通過臟檢查來實現(xiàn)數(shù)據(jù)監(jiān)測以及頁面更新渲染。之后,再接觸了vue.js,當時也一度很好奇vue.js是如何監(jiān)...
摘要:總結最后我們依照下圖參考深入淺出,再來回顧下整個過程在后,會調用函數(shù)進行初始化,也就是過程,在這個過程通過轉換成了的形式,來對數(shù)據(jù)追蹤變化,當被設置的對象被讀取的時候會執(zhí)行函數(shù),而在當被賦值的時候會執(zhí)行函數(shù)。 前言 Vue 最獨特的特性之一,是其非侵入性的響應式系統(tǒng)。數(shù)據(jù)模型僅僅是普通的 JavaScript 對象。而當你修改它們時,視圖會進行更新。這使得狀態(tài)管理非常簡單直接,不過理解...
摘要:進階系列一之響應式原理及實現(xiàn)進階系列二之插件原理及實現(xiàn)進階系列三之函數(shù)原理及實現(xiàn)什么是響應式表示一個狀態(tài)改變之后,如何動態(tài)改變整個系統(tǒng),在實際項目應用場景中即數(shù)據(jù)如何動態(tài)改變。描述符必須是這兩種形式之一,但二者不能共存,不然會出現(xiàn)異常。 (關注福利,關注本公眾號回復[資料]領取優(yōu)質前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導)showImg(https://githu...
閱讀 3152·2021-11-04 16:09
閱讀 3107·2021-09-23 11:49
閱讀 3603·2021-09-09 09:33
閱讀 3605·2021-08-18 10:22
閱讀 2041·2019-08-30 15:55
閱讀 3625·2019-08-30 15:53
閱讀 2653·2019-08-28 18:08
閱讀 888·2019-08-26 18:18