摘要:寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于版本如果你覺得排版難看,請(qǐng)點(diǎn)擊下面鏈接或者拉到下面關(guān)注公眾號(hào)也可以吧如果你覺得排版難看,請(qǐng)點(diǎn)擊下面公眾號(hào)
寫文章不容易,點(diǎn)個(gè)贊唄兄弟
專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧
研究基于 Vue版本 【2.5.17】
如果你覺得排版難看,請(qǐng)點(diǎn)擊 下面鏈接 或者 拉到 下面關(guān)注公眾號(hào)也可以吧
如果你覺得排版難看,請(qǐng)點(diǎn)擊下面公眾號(hào)鏈接
【Vue原理】Props - 白話版
今天我們用白話文解讀props 的工作原理
props 真的挺有用的,作為父?jìng)髯拥妮d體,大家肯定都用過,但是你有沒有想過,Props 到底是怎么工作的?
希望先看下 響應(yīng)式原理,對(duì) props 理解很有幫助
響應(yīng)式原理
開篇之前,我提出三個(gè)問題
1、父組件 怎么傳值給 子組件的 props
2、子組件如何讀取props
3、父組件 data 更新,子組件的props 如何更新
今天我們帶著三個(gè)問題去開始我們的講解
明白這三個(gè)問題,那么相信你也就理解了 props 的工作原理
場(chǎng)景設(shè)置現(xiàn)在我們有一個(gè)這樣的 根組件 A 和 他的 子組件 testb
根組件A 會(huì) 把 parentName 傳給 子組件 testb 的 props
根組件A 也是 組件testb 的 父組件
new Vue({ el:".a", name:"A", components:{ testb:{ props:{ childName:"" }, template: "父組件傳入的 props 的值 {{childName}}
", } }, data(){ return { parentName:"我是父組件" } }, })
按照上面的例子,開始我們的問題解析
父組件怎么傳值給子組件的 props
這部分內(nèi)容會(huì)比較多,但是這部分內(nèi)容是 props 的重中之重,必須理解好吧
根據(jù)上面的場(chǎng)景設(shè)置,testb 是一個(gè)子組件,接收一個(gè) props(child-name)
然后 根組件 A 把 自身的 parentName 綁定到 子組件的屬性 child-name 上
父組件的模板 會(huì)被解析成一個(gè) 模板渲染函數(shù)
(function() { with(this){ return _c("div",{staticClass:"a"},[ _c("testb",{attrs:{"child-name":parentName}}) ],1) } })
這段代碼需要解釋下
雖然想不涉及源碼,但是這段代碼對(duì)我們理解很有幫助,而且不難,所以決定放上來
1、_c 是渲染組件的函數(shù),_c("testb") 表示渲染 testb 這個(gè)子組件
2、因?yàn)?with 的作用是,綁定大括號(hào)內(nèi)代碼的 變量訪問作用域
3、這是一個(gè)匿名自執(zhí)行函數(shù),會(huì)在后面執(zhí)行
簡(jiǎn)化上面的函數(shù),做個(gè)例子測(cè)試一下
function test(){ with(this){ console.log(parentName) } } test.call({parentName:"測(cè)試名字"})
你能看到,我給 test 綁定了一個(gè)對(duì)象作用域,加上 with 綁定 this,然后讀取 parentName 就會(huì)從 傳入的對(duì)象上獲取
了解了這個(gè),我們來看下一步
之后,模板函數(shù)會(huì)被執(zhí)行,執(zhí)行時(shí)會(huì)綁定 父組件為作用域
所以渲染函數(shù)內(nèi)部所有的變量,都會(huì)從父組件對(duì)象 上去獲取
綁定了父作用域之后, parentName 自然會(huì)從父組件獲取,類似這樣
{ attrs: { child-name: parentVm.parentName } }
函數(shù)執(zhí)行了,內(nèi)部的 _c("testb") 第一個(gè)執(zhí)行,然后傳入了 賦值后的 attrs
父組件賦值之后的 attrs 就是下面這樣
{ attrs: { child-name: "我是父組件" } }
此時(shí),父組件就正式 利用 props 把 parentName 傳給了 子組件的props child-name
_c("testb",{attrs:{"child-name":parentName}})
而 attrs 包含 普通屬性 和 props,所以需要 篩選出 props,然后保存起來
props 會(huì)被 保存到 實(shí)例的_props 中,并且 會(huì)逐一復(fù)制到 實(shí)例上,并且每一個(gè)屬性會(huì)被設(shè)置為響應(yīng)式的
你看到的,每一個(gè) 實(shí)例都會(huì)有 一個(gè) _props 的同時(shí),也會(huì)把屬性直接放在 實(shí)例上。
我是不會(huì)騙你的好吧
組件怎么讀取 props通過上面的問題,我們知道了 子組件保存了 父組件 傳入 的數(shù)據(jù)
prop 的數(shù)據(jù)會(huì)被 逐一復(fù)制到 vm對(duì)象上(子組件的實(shí)例 this) 上
但是復(fù)制的時(shí)候,會(huì)對(duì)每個(gè)屬性,同時(shí)設(shè)置 get 和 set 函數(shù),進(jìn)行 訪問轉(zhuǎn)接 和 賦值轉(zhuǎn)接
下面是我簡(jiǎn)化了源碼的一段代碼,了解一下
Object.defineProperty(vm, key, { get() { return this._props[key] }, set(val) { this._props[key] = val } });
我以 props 其中一個(gè) 屬性 childName 為例好吧
Object.defineProperty(childVm, childName, { get() { return this._props.childName }, set(val) { this._props.childName = val } });
你訪問 props 其中一個(gè)值 vm.childName,其實(shí)訪問的是 vm._props.childName
你賦值 vm.childName= 5 ,其實(shí)是賦值 vm._props.childName= 5
但是你直接在這里給 props 賦值,你是不會(huì)影響到 父組件的data 的好吧,兩個(gè)東西完全沒有關(guān)系
就像你老爸給錢你用,你怎么用,對(duì)老爸都沒有影響
總結(jié)
移花接木,貍貓換太子,就是 props 本人了,掛羊頭賣狗肉,很明顯違法行為,欺騙消費(fèi)者
父組件數(shù)據(jù)變化,子組件props如何更新看過我上一篇文章的都知道
每一個(gè)實(shí)例都會(huì)存在 一個(gè) 專屬watcher
1、用于實(shí)例自己更新視圖
2、用于給 依賴的屬性保存,然后屬性變化的時(shí)候,通知實(shí)例更新
我已經(jīng)在 上一篇講解過 響應(yīng)式原理,如果這里你不明白,可以查看一下
【Vue原理】響應(yīng)式原理 - 白話版
以 parentName 為例,講解更新,parentName 是 父組件的 data,然后傳給子組件的props
在 父組件渲染函數(shù)中
(function() { with(this){ return _c("div",{staticClass:"a"},[ _c("testb",{attrs:{"child-name":parentName}}) ],1) } })
因?yàn)?Vue 會(huì)對(duì)組件的渲染函數(shù)進(jìn)行緩存,所以更新的時(shí)候,不需要重新解析,直接讀取緩存,會(huì)加快渲染速度
然后渲染函數(shù)執(zhí)行,開啟新一輪的 props 賦值操作,回到了第一個(gè)問題,如果不記得,可以回去看下
總結(jié)1、父組件 data 的值 和 子組件的 props 一般是沒有任何聯(lián)系的,更改 props 不影響父組件 data,但是如果傳入的是 對(duì)象,那么修改對(duì)象,是會(huì)影響父組件的,因?yàn)閿?shù)據(jù)是原樣傳入的,所以修改對(duì)象,兩個(gè)地方都會(huì)影響
2、props 也是響應(yīng)式的,跟 data 本質(zhì) 差不多
3、props 會(huì)訪問轉(zhuǎn)接,賦值轉(zhuǎn)接 ,其實(shí)操作的是 vm._props 的屬性
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/105088.html
寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請(qǐng)點(diǎn)擊 下面鏈接 或者 拉到 下面關(guān)注公眾號(hào)也可以吧 【Vue原理】Props - 源碼版 今天記錄 Props 源碼流程,哎,這東西,就算是研究過了,也真是會(huì)隨著時(shí)間慢慢忘記的。 幸好我做...
摘要:而我覺得現(xiàn)在出一個(gè)白話版,是讓大家有興趣去研究源碼的時(shí)候,可以提前理清一下思路。相當(dāng)于封裝,提取公共部分。顯然,今天我不是來教大家怎么用的,怎么用看文檔就好了,我是講解生命的真諦內(nèi)部的工作原理。而這個(gè)不會(huì)合并,直接替換掉整個(gè)選項(xiàng) 寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版...
摘要:寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于版本如果你覺得排版難看,請(qǐng)點(diǎn)擊下面鏈接或者拉到下面關(guān)注公眾號(hào)也可以吧原理白話版從模板上使用到掛載到頁面 寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于...
寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請(qǐng)點(diǎn)擊 下面鏈接 或者 拉到 下面關(guān)注公眾號(hào)也可以吧 【Vue原理】NextTick - 源碼版 之 服務(wù)Vue 初次看的兄弟可以先看 【Vue原理】NextTick - 白話版 簡(jiǎn)單了解下...
寫文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請(qǐng)點(diǎn)擊 下面鏈接 或者 拉到 下面關(guān)注公眾號(hào)也可以吧 【Vue原理】Mixins - 源碼版 今天探索的是 mixins 的源碼,mixins 根據(jù)不同的選項(xiàng)類型會(huì)做不同的處理 篇幅會(huì)有些長(zhǎng),...
閱讀 2194·2023-04-26 03:06
閱讀 3648·2023-04-26 01:51
閱讀 2117·2021-11-24 09:38
閱讀 2500·2021-11-17 17:00
閱讀 2364·2021-09-28 09:36
閱讀 970·2021-09-24 09:47
閱讀 2634·2019-08-30 15:54
閱讀 1587·2019-08-30 15:44