摘要:當(dāng)東西發(fā)售時,就會打你的電話通知你,讓你來領(lǐng)取完成更新。其中涉及的幾個步驟,按上面的例子來轉(zhuǎn)化一下你買東西,就是你要使用數(shù)據(jù)你把電話給老板,電話就是你的,用于通知老板記下電話在電話本,就是把保存在中。剩下的步驟屬于依賴更新
寫文章不容易,點個贊唄兄弟
專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧
研究基于 Vue版本 【2.5.17】
如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關(guān)注公眾號也可以吧
【Vue原理】依賴收集 - 源碼版之基本數(shù)據(jù)類型
如果對依賴收集完全沒有概念的同學(xué),可以先看我這篇
【Vue原理】響應(yīng)式原理 - 白話版
依賴收集,主要是為了解決一個問題,什么問題呢?
首先,我們都知道,Vue 的數(shù)據(jù)是響應(yīng)式更新的,一旦數(shù)據(jù)改變了,那么相應(yīng)使用到 數(shù)據(jù)的地方也會跟著改變。
那么問題來了,數(shù)據(jù)改變的時候,Vue 怎么知道,去讓那些使用到數(shù)據(jù)的地方也改變呢?
這就是依賴收集要解決的問題!
他是怎么解決的?簡單說就是把依賴了數(shù)據(jù)的地方,給集中收集起來以便變化后通知!我們今天來看源碼的流程
首先,響應(yīng)式更新,分為兩步,依賴收集和依賴更新
今天講的是依賴收集,如何去收集 使用了數(shù)據(jù)的地方
依賴收集,又分為兩個流程
1、數(shù)據(jù)初始化流程
2、依賴收集流程
當(dāng)前篇,先以基本數(shù)據(jù)類型為例講解,因為 基本數(shù)據(jù)和 引用數(shù)據(jù) 在處理上有很大的不同,引用類型需要理解的東西更多更復(fù)雜,所以需要循序漸進(jìn),分兩篇描述
數(shù)據(jù)初始化流程首先,在實例初始化的時候,需要對數(shù)據(jù)進(jìn)行響應(yīng)式處理,也就是給每個屬性都使用 Object.defineProperty 處理
處理的流程是怎么樣的呢?
1、實例初始化中,調(diào)用 initState 處理部分選項數(shù)據(jù),initData 用于處理選項 data
Vue.prototype._init=function(){ ... initState(this) ... } function initState(vm) { var opts = vm.$options; ... props,computed,watch 等選項處理 if (opts.data) { initData(vm); } };
2、initData 遍歷 data,definedReactive 處理每個屬性
function initData(vm) { var data = vm.$options.data; data = typeof data === "function" ? data.call(vm, vm) : data || {}; // ... 遍歷 data 數(shù)據(jù)對象的key,重名檢測,合規(guī)檢測等代碼 new Observer(data); } function Observer(value) { var keys = Object.keys(value); // ...被省略的代碼 for (var i = 0; i < keys.length; i++) { defineReactive(obj, keys[i]); } };
3、definedReactive 給對象的屬性 通過 Object.defineProperty 設(shè)置響應(yīng)式
function defineReactive(obj, key) { // dep 用于中收集所有 依賴我的 東西 var dep = new Dep(); var val = obj[key] Object.defineProperty(obj, key, { enumerable: true, configurable: true, get() { ...依賴收集,詳細(xì)源碼下個流程放出 }, set() { ....依賴更新,源碼下篇文章放出 } }); }依賴收集流程
寫一個小例子來解析
new Vue({ el: document.getElementsByTagName("div")[0], data(){ return { name:11 } } })
頁面模板
頁面引用了數(shù)據(jù) name,name 需要保存 頁面的watcher,以便于 name 變化時,通知 頁面watcher 更新
1、頁面渲染函數(shù)
with(this){ return _c("div",{},[name]) }
2、讀取 name
渲染函數(shù)執(zhí)行,上下文對象綁定為 實例,于是name讀取到實例上的 name
3、保存 watcher
name 被讀取,自然走到 Object.defineProperty.get 方法上,從這里開始收集 watcher
先來觀察下 defineReactive 中省略的 get 的源碼
function defineReactive(obj, key) { var dep = new Dep(); var val = obj[key] Object.defineProperty(obj, key, { get() { if (Dep.target) { // 收集依賴 dep.addSub(Dep.target) } return val } }); }
哈哈哈,這里就有意思了,這段代碼就是 依賴收集的核心,主要是三個點
Dep.target
Dep
dep.addSub
1、Dep.target
Dep.target 指向的是各種 watcher,watch的watcher,頁面的watcher 等等
Dep.target 是變化的,根據(jù)當(dāng)前解析流程,不停地指向不同的 watcher (指向,其實就是直接賦值 ,如下)
Dep.target = 具體watcher
“當(dāng)然沒有這么簡單,就是表示一個意思而已”
簡單想,指向哪個watcher,那么就是那個 watcher 正在使用數(shù)據(jù),數(shù)據(jù)就要收集這個watcher
你可以先不用管 Dep.target 到底是怎么指向,你只用記住 在 watcher
比如當(dāng)前頁面開始渲染時,Dep.target 會提前指向當(dāng)前頁面的 watcher。
于是頁面渲染函數(shù)執(zhí)行,并引用了數(shù)據(jù) name 后,name 直接收集 Dep.target,就會收集到當(dāng)前頁面的 watcher
watcher 有負(fù)責(zé)實例更新的功能,所以會被收集起來,數(shù)據(jù)變化時通知 watcher,就可以調(diào)用 watcher 去更新了
watcher 在 依賴收集中只起到被收集的作用,所以不會在這里詳細(xì)解釋
2、Dep
Dep 是一個構(gòu)造函數(shù),用于創(chuàng)建實例,并帶有很多方法
實例會包含一個屬性 subs 數(shù)組,用于存儲不同數(shù)據(jù) 【收集的依賴】
看下dep的構(gòu)造函數(shù)
var Dep = function Dep() { // 保存watcher 的數(shù)組 this.subs = []; };
3、dep.addSub
原型上的方法,作用是往 dep.subs 存儲器中 中直接添加 watcher
Dep.prototype.addSub = function(sub) { this.subs.push(sub); };
所以,【dep.addSub(Dep.target) 】就會直接添加當(dāng)前 watcher
于是,收集流程大概是這樣
1、頁面的渲染函數(shù)執(zhí)行, name 被讀取
2、觸發(fā) name的 Object.defineProperty.get 方法
3、于是,頁面的 watcher 就會被收集到 name 專屬的閉包dep 的 subs 中
總結(jié)為什么需要依賴收集,之前也已經(jīng)說過,是為了變化時通知 那些使用過數(shù)據(jù)的地方
就好比,你去商店買東西,東西還沒有發(fā)售,于是你把你的電話給老板,老板把你的記在電話本上。當(dāng)東西發(fā)售時,就會打你的電話通知你,讓你來領(lǐng)?。ㄍ瓿筛拢?/p>
其中涉及的幾個步驟,按上面的例子來轉(zhuǎn)化一下
1、你買東西,就是你要使用數(shù)據(jù) name
2、你把電話給老板,電話就是你的 watcher,用于通知
3、老板記下電話在電話本,就是把 watcher 保存在 subs 中。
4、剩下的步驟屬于依賴更新
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/109953.html
摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關(guān)注公眾號也可以吧原理依賴收集源碼版之引用數(shù)據(jù)類型上 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于...
摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關(guān)注公眾號也可以吧原理依賴更新源碼版如果對依賴收集完 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于...
寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關(guān)注公眾號也可以吧 【Vue原理】Props - 源碼版 今天記錄 Props 源碼流程,哎,這東西,就算是研究過了,也真是會隨著時間慢慢忘記的。 幸好我做...
摘要:因為失去焦點之后被強制更新了一波嗯,這就是的作用,把頁面上的顯示值也過濾一遍 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關(guān)注公眾號也可以吧 【Vue原理】VModel - 源碼版之input詳...
摘要:我們都知道分為普通和作用域,兩個內(nèi)容都很多,所以分兩部分進(jìn)行講述。今天講的是普通其實普通,表示默認(rèn)和具名,只是他們的處理方式都差不多,就只是是否有自定義名字而已,所以,表示一種類型。 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請...
閱讀 782·2023-04-25 15:13
閱讀 1403·2021-11-22 12:03
閱讀 829·2021-11-19 09:40
閱讀 1914·2021-11-17 09:38
閱讀 1718·2021-11-08 13:18
閱讀 660·2021-09-02 15:15
閱讀 1774·2019-08-30 15:54
閱讀 2641·2019-08-30 11:12