摘要:要想理解原理就得看源碼,最近網(wǎng)上也找了好多初始化方法個惡魔。。。因為也是循序漸進的理解,對計算屬性的初始化有幾處看得不是很明白,網(wǎng)上也都是含糊其辭的要想深入必須深入。。。
要想理解原理就得看源碼,最近網(wǎng)上也找了好多vue初始化方法(8個init惡魔。。。)
因為也是循序漸進的理解,對initComputed計算屬性的初始化有幾處看得不是很明白,網(wǎng)上也都是含糊其辭的(要想深入必須深入。。。),所以debug了好幾天,才算是有點頭緒,現(xiàn)在寫出來即幫自己再次理下思路,也可以讓大佬指出錯誤
首先,基本的雙向綁定原理就不說了,可以去搜下相關(guān)教程,還是要先理解下簡單的例子
進入正題,先來看下initComputed的源碼結(jié)構(gòu),這之前還是先放一個例子也好說明function initComputed (vm, computed) { console.log("%cinitComputed","font-size:20px;border:1px solid black") var watchers = vm._computedWatchers = Object.create(null); // computed properties are just getters during SSR var isSSR = isServerRendering(); for (var key in computed) { var userDef = computed[key]; var getter = typeof userDef === "function" ? userDef : userDef.get; if ("development" !== "production" && getter == null) { warn( ("Getter is missing for computed property "" + key + ""."), vm ); } //minxing---console console.log("%cinitComputed 定義watchers[key]=new Watcher(vm getter noop computedWatcherOptions)","color:white;padding:5px;background:black"); if (!isSSR) { // create internal watcher for the computed property. /** * 熟悉的newWatcher,創(chuàng)建一個訂閱者,為了之后收集依賴 * 將例子中的num、lastNum和計算屬性comNum進行綁定 * 也就是說在一個deps中有兩個dep,其中的subs分別是 * dep1.subs:[watcher(num),watcher(comNum)] * dep2.subs:[watcher(lastNum),watcher(comNum)] * dep3........ * 請看前面的例子,頁面html中并沒有渲染{{lastNum}};按理說就不會執(zhí)行l(wèi)astNum的getter * 從而就不會和計算屬性進行關(guān)聯(lián)綁定,如果更改lastNum就不會觸發(fā)dep2的notify()發(fā)布 * 自然也就不會在頁面看到comNum有所變化,但是運行后卻不是這樣,為什么呢 * 這就引出這個initComputed的下面方法了---依賴收集(watcher.prototype.depend)! * 當時也是看了好久才知道這個depend方法的作用,后面再說 * 首先先來提個頭,就是下面代碼中watcher中這個getter * 其實就是function comNum() {return this.num+"-computed-"+this.lastNum;}} * 而這個getter什么時候執(zhí)行呢,會在Watcher.prototype.evaluate()方法中執(zhí)行 * 所以watcher中的evaluate()與depend()兩個方法都與initComputed相關(guān) */ watchers[key] = new Watcher( vm, getter || noop, noop, computedWatcherOptions ); } // component-defined computed properties are already defined on the // component prototype. We only need to define computed properties defined // at instantiation here. // 經(jīng)過判斷后定義計算屬性---(關(guān)聯(lián)到vm的data上面) if (!(key in vm)) { defineComputed(vm, key, userDef); } else { if (key in vm.$data) { warn(("The computed property "" + key + "" is already defined in data."), vm); } else if (vm.$options.props && key in vm.$options.props) { warn(("The computed property "" + key + "" is already defined as a prop."), vm); } } } }defineComputed方法
這個方法比較簡單主要就是將計算屬性綁定到vm上,重要的下面的createComputedGetter方法
function defineComputed ( target, key, userDef ) { console.log("%cdefineComputed","font-size:20px;border:1px solid black") var shouldCache = !isServerRendering(); if (typeof userDef === "function") { sharedPropertyDefinition.get = shouldCache ? createComputedGetter(key) : userDef; sharedPropertyDefinition.set = noop; } else { sharedPropertyDefinition.get = userDef.get ? shouldCache && userDef.cache !== false ? createComputedGetter(key) : userDef.get : noop; sharedPropertyDefinition.set = userDef.set ? userDef.set : noop; } if ("development" !== "production" && sharedPropertyDefinition.set === noop) { sharedPropertyDefinition.set = function () { warn( ("Computed property "" + key + "" was assigned to but it has no setter."), this ); }; } Object.defineProperty(target, key, sharedPropertyDefinition); }
function createComputedGetter (key) { console.log("createComputedGetter key",key); return function computedGetter () { var watcher = this._computedWatchers && this._computedWatchers[key]; if (watcher) { if (watcher.dirty) { watcher.evaluate(); } if (Dep.target) { watcher.depend(); } return watcher.value } } }createComputedGetter方法,主要做了兩件事 1 求計算屬性的值---利用上面說的調(diào)用watcher.evalute()方法,執(zhí)行watcher中的getter 2 依賴收集綁定,這點最重要,就是上面說過的如果沒有在html中對計算屬性相關(guān)聯(lián)的data屬性(lastNum)進行頁面渲染的話,watcher.depend()此方法就會執(zhí)行這個依賴收集綁定的作用dep.subs[watcher(計算屬性),watcher(計算關(guān)聯(lián)屬性1),...],這樣的話當你更改lastNum就會觸發(fā)對應的dep.notify()方法發(fā)布通知訂閱者執(zhí)行update,進行數(shù)據(jù)更新了,而如果將watcher.depend()方法注釋掉,而頁面中將lastNum渲染({{lastNum}}),此時watcher.evalute()會執(zhí)行watcher.get從而將此計算watcher推入dep.target中,而渲染lastNum執(zhí)行g(shù)etter的時候就會將此watcher加入依賴,所以也會將lastNum和計算屬性關(guān)聯(lián)到dep中
function createComputedGetter (key) { console.log("createComputedGetter key",key); return function computedGetter () { var watcher = this._computedWatchers && this._computedWatchers[key]; if (watcher) { if (watcher.dirty) { console.log("createComputedGetter watcher evaluate==========="); //求值 watcher.evaluate(); } if (Dep.target) { console.log("createComputedGetter watcher depend==========="); //依賴收集 watcher.depend(); } console.log("%ccreateComputedGetter watcher.value is","color:blue;font-size:40px",watcher.value); return watcher.value } } }
為了更好的說明下,截兩張圖(都是基于最上面的html配置哦)
圖組一注釋掉watcher.depend()方法,此時deps中沒有dep:id4
其實dep:id4在內(nèi)存中已經(jīng)定義好了但是沒有加入到deps中(因為沒有進行依賴收集)
而dep:id5和id6就是上面的數(shù)組和遞歸數(shù)組中元素的dep
dep:id3 就是
這下是不是很清楚了
進行依賴收集后的deps
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/51731.html
摘要:要想理解原理就得看源碼,最近網(wǎng)上也找了好多初始化方法個惡魔。。。因為也是循序漸進的理解,對計算屬性的初始化有幾處看得不是很明白,網(wǎng)上也都是含糊其辭的要想深入必須深入。。。 要想理解原理就得看源碼,最近網(wǎng)上也找了好多vue初始化方法(8個init惡魔。。。) 因為也是循序漸進的理解,對initComputed計算屬性的初始化有幾處看得不是很明白,網(wǎng)上也都是含糊其辭的(要想深入必須深入。。...
摘要:代碼初始化部分一個的時候做了什么當我們一個時,實際上執(zhí)行了的構(gòu)造函數(shù),這個構(gòu)造函數(shù)內(nèi)部掛載了很多方法,可以在我的上一篇文章中看到。合并構(gòu)造函數(shù)上掛載的與當前傳入的非生產(chǎn)環(huán)境,包裝實例本身,在后期渲染時候,做一些校驗提示輸出。 概述 在使用vue的時候,data,computed,watch是一些經(jīng)常用到的概念,那么他們是怎么實現(xiàn)的呢,讓我們從一個小demo開始分析一下它的流程。 dem...
摘要:并在內(nèi)執(zhí)行了函數(shù),在函數(shù)內(nèi)部,訪問了。至此知道了它依賴于。需要根據(jù)最新的計算。本例中收集到了依賴并且也被告知觀察了他們。文章鏈接源碼分析系列源碼分析系列之環(huán)境搭建源碼分析系列之入口文件分析源碼分析系列之響應式數(shù)據(jù)一源碼分析系列之響應式數(shù)據(jù)二 前言 上一節(jié)著重講述了initData中的代碼,以及數(shù)據(jù)是如何從data中到視圖層的,以及data修改后如何作用于視圖。這一節(jié)主要記錄initCo...
摘要:被讀取,包裝的函數(shù)觸發(fā),第一次會進行計算被調(diào)用,進而被調(diào)用,被設置為,舊值頁面被緩存起來。計算會讀取,此時就收集到同時也會保存到的依賴收集器用于下一步。 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學習吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下...
摘要:源碼對于計算屬性的理解這是我最近學習源碼的一個個人總結(jié)和理解,所以可能并不適合每一位讀者本文的整體脈絡如下,首先盡可能去掉細節(jié),對計算屬性源碼的大致實現(xiàn)有一個了解,然后舉一例子,分別談談計算屬性依賴收集和派發(fā)更新的流程。 vue源碼-對于「計算屬性」的理解 這是我最近學習vue源碼的一個個人總結(jié)和理解,所以可能并不適合每一位讀者 本文的整體脈絡如下,首先盡可能去掉細節(jié),對計算屬性源碼的...
閱讀 2270·2019-08-30 15:56
閱讀 3108·2019-08-30 13:48
閱讀 1123·2019-08-30 10:52
閱讀 1490·2019-08-29 17:30
閱讀 417·2019-08-29 13:44
閱讀 3528·2019-08-29 12:53
閱讀 1113·2019-08-29 11:05
閱讀 2667·2019-08-26 13:24