摘要:其成員函數最主要的是和,前者用來設置某個的依賴,后者則用來通知與這個依賴相關的來運行其回調函數。也就是進行數據更新操作。
vue框架的兩個抽象核心:虛擬DOM和相應式數據原理
關于虛擬DOM的核心算法,我們上一章已經基本解析過了,詳細的見
React && VUE Virtual Dom的Diff算法統一之路 snabbdom.js解讀
關于響應式數據原理,我們先看張圖
你 ‘ (4).png
具體來講,要分以下幾步:
初始化實例對象時運行initState, 建立好props, data 的鉤子以及其對象成員的Observer, 對于computed 屬性,則建立起所有對應的 Watcher 并且通過 Object.defineProperty 在vm對象上設置一個該屬性的 getter。同時還根據自定義的 watch 來建立相應的 Watcher
執行掛載操作,在掛載時建立一個直接對應render(渲染)的 Watcher,并且編譯模板生成 render 函數,執行vm._update 來更新 DOM 。
此后每當有數據改變,都將通知相應的 Watcher 執行回調函數。
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) }
如果是數組類型則會遞歸調用,建立依賴體系
否則則調用walk()函數去利用Object.defineProperty簡歷依賴
那么defineReactive是如何實現的呢,如下
//省略了部分代碼 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數組中的依賴關系
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 所對應的數據依賴,在這個對象中也存有一個 subs 數組,用來保存和這個依賴有關的 Watcher。其成員函數最主要的是 depend 和 notify ,前者用來設置某個 Watcher 的依賴,后者則用來通知與這個依賴相關的 Watcher 來運行其回調函數。
我們知道,Dom 上通過指令或者雙大括號綁定的數據,會為數據進行添加觀察者watcher,當實例化Watcher的時候 會觸發屬性的getter方法,此時會調用dep.depend()。我們看一下depend方法:
depend () { if (Dep.target) { Dep.target.addDep(this) } }
Dep.target 是什么東西呢?其實在進行Watcher實例化的時候,會調用內部的get函數,開始為他初始化
Watcher 觀察者其中pushTarget 方法就是為Dep.target綁定此watcher實例,所以Dep.target.addDep(this)也就是執行此實例中的addDep方法
addDep (dep: Dep) { ... dep.addSub(this) }
這樣便為我們的dep實例添加了一個watcher實例。
接著當我們更新data的時候,會觸發他的set方法,執行dep.notify()函數:
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()。也就是進行數據更新操作。這也就是簡單的數據響應式,其實還需要注意的是: 當數據的getter觸發后,會收集依賴,但也不是所有的觸發方式都會收集依賴,只有通過watcher觸發的getter會收集依賴:if (Dep.target) { dep.depend() },而所謂的被收集的依賴就是當前watcher,DOM中的數據必須通過watcher來綁定,只通過watcher來讀取。
最后付一個函數timeline
的.png
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/102995.html
摘要:下面我們會向大家解釋清楚為什么這個這么重要,以及它和的響應式數據流有什么關系。源碼前面鋪墊這么多就是希望大家能理解接下來要講的響應式數據流。總結講到這里大家應該都能夠明白的響應式數據流是如何實現的。 Vue、React介紹 目前前端社區比較推崇的框架有Vue 和 React,公司內部許多端都自發的將原有的老技術方案(widget + jQuery)遷移到 Vue / React上了。我...
摘要:今天,就我們就來一步步解析響應式的原理,并且來實現一個簡單的。當然,這個也只是一個簡單的,來說明響應式的原理,真實的源碼會更加復雜,因為加了很多其他邏輯。接下來我可能會將其與聯系起來,實現和語法。 從很久之前就已經接觸過了angularjs了,當時就已經了解到,angularjs是通過臟檢查來實現數據監測以及頁面更新渲染。之后,再接觸了vue.js,當時也一度很好奇vue.js是如何監...
摘要:總結最后我們依照下圖參考深入淺出,再來回顧下整個過程在后,會調用函數進行初始化,也就是過程,在這個過程通過轉換成了的形式,來對數據追蹤變化,當被設置的對象被讀取的時候會執行函數,而在當被賦值的時候會執行函數。 前言 Vue 最獨特的特性之一,是其非侵入性的響應式系統。數據模型僅僅是普通的 JavaScript 對象。而當你修改它們時,視圖會進行更新。這使得狀態管理非常簡單直接,不過理解...
摘要:進階系列一之響應式原理及實現進階系列二之插件原理及實現進階系列三之函數原理及實現什么是響應式表示一個狀態改變之后,如何動態改變整個系統,在實際項目應用場景中即數據如何動態改變。描述符必須是這兩種形式之一,但二者不能共存,不然會出現異常。 (關注福利,關注本公眾號回復[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導)showImg(https://githu...
閱讀 3163·2021-11-04 16:09
閱讀 3131·2021-09-23 11:49
閱讀 3648·2021-09-09 09:33
閱讀 3633·2021-08-18 10:22
閱讀 2048·2019-08-30 15:55
閱讀 3636·2019-08-30 15:53
閱讀 2662·2019-08-28 18:08
閱讀 898·2019-08-26 18:18