摘要:通過(guò)函數(shù)參數(shù)傳遞的形式,讓插槽的變量,在解析時(shí),先訪問(wèn)函數(shù)變量。那么這兩個(gè)有什么關(guān)系呢外殼節(jié)點(diǎn)保存著所有父組件里給這個(gè)子組件綁定的數(shù)據(jù),比如,插槽等。
寫(xiě)文章不容易,點(diǎn)個(gè)贊唄兄弟
專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧
研究基于 Vue版本 【2.5.17】
如果你覺(jué)得排版難看,請(qǐng)點(diǎn)擊 下面鏈接 或者 拉到 下面關(guān)注公眾號(hào)也可以吧
【Vue原理】Slot - 源碼版之作用域插槽
今天探索Slot的另一部分,作用域插槽。
首先,設(shè)置一個(gè)模板例子
把子組件的 child 傳給 插槽
父組件會(huì)解析成下面的渲染函數(shù)
with(this) { return _c("div", {}, [_c("test", { scopedSlots: _u([{ key: "default", fn: function(slotProps) { return [ "我是放在組件的 slot :"+slotProps ] } }]) })], 1) }
其中,_u 是 resolveScopedSlots,Vue會(huì)給每個(gè)實(shí)例都注冊(cè)一個(gè) _u 方法。
作用主要是把數(shù)組變成對(duì)象map并返回
看下 resolveScopedSlots 源碼
給每個(gè)實(shí)例注冊(cè) _u
function resolveScopedSlots(fns, res) { res = res || {}; for (var i = 0; i < fns.length; i++) { res[fns[i].key] = fns[i].fn; } return res }
把傳入的數(shù)組組裝成對(duì)象,像是下面這樣
[{ key: "default", fn: function(slotProps) { return ["我是放在組件的 slot :" + slotProps] } }] ---------_u 把上面變成下面------ { default:function(slotProps) { return ["我是放在組件的 slot :" + slotProps] } }插槽怎么解析
你可以看到了,在父組件的渲染函數(shù)中,作用域Slot 被包裝成了一個(gè)函數(shù),并且保存在 test 組件的 scopeSlot 中,用于后面解析內(nèi)部組件時(shí)使用
包裝成函數(shù),是為了改變插槽內(nèi)容的變量訪問(wèn)的作用域。
通過(guò)函數(shù)參數(shù)傳遞的形式,讓插槽的變量,在解析時(shí),先訪問(wèn)函數(shù)變量。如果沒(méi)有,再去父組件上獲取
那么這個(gè)函數(shù)的參數(shù)是從哪里傳進(jìn)來(lái)的呢?讓我們一探究竟
額外:組件解析
上面的 test 在父組件中解析成一個(gè)節(jié)點(diǎn)
{ tag:"test", children:["我是放在組件的 slot :11"] }
而解析 test 時(shí),也會(huì)被解析成一個(gè)節(jié)點(diǎn)
{ tag:"main", children:["我在子組件里面","我是放在組件的 slot :11"] }
就是 test 會(huì)有兩個(gè)節(jié)點(diǎn),第一個(gè)節(jié)點(diǎn)我認(rèn)為是外殼節(jié)點(diǎn),第二個(gè)節(jié)點(diǎn)是渲染節(jié)點(diǎn),是真正插入頁(yè)面的。
那么這兩個(gè)有什么關(guān)系呢?外殼節(jié)點(diǎn)保存著所有父組件里給這個(gè)子組件綁定的數(shù)據(jù),比如 props,插槽等。然后提供給 組件解析時(shí)使用
按順序理一下解析流程
1、插槽函數(shù)保存到外殼節(jié)點(diǎn)
之前的父渲染函數(shù),子組件的插槽解析成一個(gè)節(jié)點(diǎn)處理函數(shù),如下 ,然后作為 scopedSlots 保存在 test 組件的外殼節(jié)點(diǎn)上
{ tag:"test", data:{ scopedSlots:{ // 插槽包裝成的函數(shù) default:function(slotProps) { return [ "我是放在組件的 slot :"+slotProps ] } } }, children:["我是放在組件的 slot :11"] }
2、插槽函數(shù)另存為
然后,test組件會(huì)創(chuàng)建自身實(shí)例,并且初始化,在初始化的過(guò)程中,會(huì)把 外殼節(jié)點(diǎn)上的 $scopedSlots 另存為到本實(shí)例上,方便后面子組件解析內(nèi)部模板直接調(diào)用
// 這個(gè)函數(shù)作用是,執(zhí)行渲染函數(shù),得到組件節(jié)點(diǎn) Vue.prototype._render = function() { var vm = this; var ref = vm.$options; // _parentVnode 就是外殼節(jié)點(diǎn) var _parentVnode = ref._parentVnode; if (_parentVnode) { vm.$scopedSlots = _parentVnode.data.scopedSlots || {}; } ...省略N多執(zhí)行渲染函數(shù)的代碼 vm.$vnode = _parentVnode; return vnode };
3、子組件解析內(nèi)部
看下子組件模板,綁定了child在 slot 上,用于傳給插槽
執(zhí)行子組件解析成的渲染函數(shù)如下
with(this) { return _c("main", [ "我在子組件里面", _t("default", null, { child: child }) ], 2) }
其中,child 會(huì)從子組件上獲取,所以 child 是11
渲染函數(shù)中,看到子組件中的slot的占位標(biāo)簽如下
被解析成了一個(gè)_t函數(shù)(怎么解析的話,又是一篇,太多先不說(shuō))
_t("default", null, { child:child })
看下_t,他是renderSlot,上一篇文章提過(guò)。這個(gè)方法,會(huì)兼容處理作用域Slot和普通Slot,上篇文章省略了處理作用域Slot 的代碼,現(xiàn)在看一下
function renderSlot(name, fallback, props) { // 看了上面,所以可以從實(shí)例上獲取$scopedSlots var scopedSlotFn = this.$scopedSlots[name]; var nodes; if (scopedSlotFn) { props = props || {}; // 開(kāi)始執(zhí)行插槽函數(shù) nodes = scopedSlotFn(props); } return nodes }
_t 的作用是,執(zhí)行會(huì)直接返回節(jié)點(diǎn),直接替換子組件 slot 占位符,完成插入功能
_t 就是 renderSlot ,函數(shù)會(huì)根據(jù) 【插槽名字】 找到對(duì)應(yīng)的 【作用域Slot包裝成的函數(shù)】,然后執(zhí)行它,把子組件內(nèi)的數(shù)據(jù) 【 { child:child } 】子傳進(jìn)去
于是,作用域Slot 生成的函數(shù),就接收到了子組件傳入的數(shù)據(jù)啦
所以 作用域Slot 就可以拿傳入的參數(shù)進(jìn)行解析了
插槽怎么插入子組件_t("default",null,{ child:child }) 執(zhí)行完畢,會(huì)返回節(jié)點(diǎn),這個(gè)節(jié)點(diǎn)就是 slot 解析生成的節(jié)點(diǎn)
[ "我是放在組件的 slot :"+ {child:11} ]
子組件渲染函數(shù)執(zhí)行完畢,生成的vnode 如下
{ tag:"main", children:[ "我在子組件里面", "我是放在組件的 slot : {child:11}" ] }
作用域插槽,成功地替換了原來(lái)的占位符
最后,來(lái)張圖看下總的流程
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/105321.html
摘要:我們都知道分為普通和作用域,兩個(gè)內(nèi)容都很多,所以分兩部分進(jìn)行講述。今天講的是普通其實(shí)普通,表示默認(rèn)和具名,只是他們的處理方式都差不多,就只是是否有自定義名字而已,所以,表示一種類型。 寫(xiě)文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺(jué)得排版難看,請(qǐng)...
摘要:寫(xiě)文章不容易,點(diǎn)個(gè)贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于版本如果你覺(jué)得排版難看,請(qǐng)點(diǎn)擊下面鏈接或者拉到下面關(guān)注公眾號(hào)也可以吧原理白話版插槽作為組件一個(gè)重要的部 寫(xiě)文章不容易,點(diǎn)個(gè)贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于...
摘要:網(wǎng)絡(luò)上大多數(shù)文章,也是千篇一律的翻譯這句話,可是僅憑這一句話,我想象不到的使用場(chǎng)景。因?yàn)檎嬲氖褂脠?chǎng)景下,子組件的數(shù)據(jù)都是來(lái)自父組件的。組件的數(shù)據(jù)都是來(lái)自調(diào)用者的,然后會(huì)把每一行的,在開(kāi)發(fā)者需要時(shí),傳遞出去。 Vue的slot-scope的場(chǎng)景的個(gè)人理解 這篇文章不是單純把文檔的話和api拿來(lái)翻譯和演示,而是談?wù)勎覍?duì)于slot-scope的使用場(chǎng)景的個(gè)人理解,如果理解錯(cuò)誤,歡迎討論! ...
摘要:結(jié)合我們的例子,子組件則會(huì)生成以下代碼到目前為止,對(duì)于普通插槽和作用域插槽已經(jīng)談的差不多了。下面我們將仔細(xì)談?wù)勥@塊的內(nèi)容。在看具體實(shí)現(xiàn)邏輯前,我們先通過(guò)一個(gè)例子來(lái)先了解下其基本用法然后進(jìn)行使用頁(yè)面展示效果如下看著好。本篇文章是細(xì)談 vue 系列第二篇了,上篇我們已經(jīng)細(xì)談了 vue 的核心之一 vdom,傳送門 今天我們將分析我們經(jīng)常使用的 vue 功能 slot 是如何設(shè)計(jì)和實(shí)現(xiàn)的,本文將圍...
摘要:后將已廢棄的使用特性的語(yǔ)法廢除,但是目前還能夠使用,鏈接地址如圖實(shí)現(xiàn)一個(gè)類似,星級(jí)點(diǎn)評(píng)的組件父組件子組件子組件將綁定再傳給父組件的再通過(guò)獲得傳過(guò)來(lái)的值,官方解釋作用域插槽的內(nèi)部工作原理是將你的插槽內(nèi)容包括在一個(gè)傳入單個(gè)參數(shù)的函數(shù)里插槽 vue 2.6.0后將已廢棄的使用 slot-scope 特性的語(yǔ)法廢除,但是目前還能夠使用,鏈接地址:https://cn.vuejs.org/v2/...
閱讀 788·2021-11-24 10:19
閱讀 1187·2021-09-13 10:23
閱讀 3509·2021-09-06 15:15
閱讀 1835·2019-08-30 14:09
閱讀 1768·2019-08-30 11:15
閱讀 1905·2019-08-29 18:44
閱讀 998·2019-08-29 16:34
閱讀 2520·2019-08-29 12:46