vue的插槽用法,官方文檔寫的內(nèi)容個(gè)人感覺有點(diǎn)亂,不自己梳理一下的話,使用的時(shí)候也容易懵逼,下面是我對(duì)vue插槽使用的理解:
1.概念
slot概念源于web components規(guī)范草案(地址:https://github.com/WICG/webcomponents/blob/gh-pages/proposals/Slots-Proposal.md)
vue官網(wǎng)關(guān)于插槽的文檔中藕赞,第一句話即說明了vue的slot插槽設(shè)計(jì)源于web components,具體內(nèi)容可以自行了解卖局,這里只說vue框架下slot的用法斧蜕。
概念:slot可將父組件在子組件標(biāo)簽里寫的content渲染到子組件對(duì)應(yīng)的地方
2.用法
先說通用性用法,再說特殊情況會(huì)讓人比較容易接受砚偶。這里以最具通用性的寫法批销,以具名插槽的寫法為例子展開
父組件中:
<script>
...
</script>
<template> // 注意這個(gè)template是組件的template屬性,不要跟下面的template標(biāo)簽弄混
<todo-item>
<template v-slot:default> // 注意v-slot指令大多數(shù)情況都是寫在template標(biāo)簽里染坯,有一種特殊情況在下一節(jié)會(huì)說到均芽,即使不懂特殊情況也不會(huì)妨礙到使用。
這里的內(nèi)容會(huì)渲染到子組件對(duì)應(yīng)的地方
</template>
</todo-item>
</template>
<style>
...
</style>
子組件中
<div>
// 子組件中slot標(biāo)簽的name屬性值與父組件中的v-slot綁定的屬性值一致单鹿,形成對(duì)應(yīng)關(guān)系
<slot name="default"></slot>
</div>
渲染結(jié)果:
<div>
這里的內(nèi)容會(huì)渲染到子組件對(duì)應(yīng)的地方
</div>
父組件template標(biāo)簽上的v-slot指令與子組件的slot標(biāo)簽的name屬性掀宋,通過綁定一樣的值,形成一一對(duì)應(yīng)的關(guān)系仲锄。
父組件中:
<子組件標(biāo)簽>
<template v-slot:default>
我會(huì)渲染到name=default的slot中
</template>
<template v-slot:test1>
我會(huì)渲染到name=test1的slot中
</template>
<template v-slot:test2>
我會(huì)渲染到name=test2的slot中
</template>
</子組件標(biāo)簽>
子組件中:
<div>
<slot name="default"></slot> // 我會(huì)渲染到name=default的slot中
</div>
<div>
<slot name="test1"></slot> // 我會(huì)渲染到name=test1的slot中
</div>
<div>
<slot name="test2"></slot> // 我會(huì)渲染到name=test2的slot中
</div>
注意劲妙,上述例子中,都有v-slot綁定default屬性的情況儒喊,這里需要說明下镣奋,vue中的插槽用法,default屬性的模板和插槽存在特殊的對(duì)應(yīng)情況怀愧,而比較容易混亂的點(diǎn)就在這里侨颈,這也是vue官網(wǎng)插槽文檔讓人看得很蒙圈的地方,因?yàn)楣倬W(wǎng)并沒有給我們分區(qū)域的講述通用情況和特殊情況芯义,而是穿插著講哈垢,讓人容易理不清楚關(guān)系。
3.插槽的默認(rèn)值
子組件的slot標(biāo)簽中的值可以寫入內(nèi)容毕贼,這部分內(nèi)容會(huì)在沒有對(duì)應(yīng)的模板內(nèi)容的時(shí)候,作為默認(rèn)值展示
父組件
<todo-item>
<template v-slot:test1>
我是模板1
</template>
</todo-item>
子組件
<div>
<slot name="test1">
我是插槽1
</slot>
</div>
<div>
<slot name="test2">
我是插槽2
</slot>
</div>
渲染結(jié)果
<div>
我是模板1
</div>
<div>
我是插槽2
</div>
4.v-slot指令動(dòng)態(tài)綁定屬性
<script>
export default {
data() {
return {
slotName: 'test1'
}
}
}
</script>
<template>
<todo-item>
<template v-slot:[slotName]>
</template>
</todo-item>
</template>
<style>
</style>
具名插槽的寫法具備通用性蛤奢,學(xué)會(huì)了具名插槽寫法鬼癣,那么插槽的用法已經(jīng)能夠掌握8成了陶贼。下面將展開的是插槽中的特殊對(duì)應(yīng)關(guān)系
5.default模板和插槽中的特殊對(duì)應(yīng)關(guān)系
------------默認(rèn)的default模板和插槽-----------
父組件
<todo-item>
我是default的內(nèi)容
<template v-slot:test>
我會(huì)渲染到name=test的slot標(biāo)簽中
</template>
我也是default的內(nèi)容
</todo-item>
子組件情形1
<div>
<slot></slot>
</div>
子組件情形2
<div>
<slot name="default"></slot>
</div>
渲染結(jié)果都是
<div>
我是default的內(nèi)容 我也是default的內(nèi)容
</div>
由于兩種情形中都沒有name屬性是test的插槽,所以渲染結(jié)果中沒有出現(xiàn)test模板里的內(nèi)容待秃。
上述例子中涵蓋了2個(gè)知識(shí)點(diǎn)拜秧,首先通過子組件情形2能得到渲染結(jié)果,可以得出一個(gè)結(jié)論:
①.父組件中只要是不在template里的內(nèi)容章郁,無論內(nèi)容在什么位置(必須在子組件標(biāo)簽里)枉氮,默認(rèn)都是default模板的內(nèi)容,即
<todo-item>
我是default的內(nèi)容 // 默認(rèn)算default模板內(nèi)容
<template v-slot:test>
我會(huì)渲染到name=test的slot標(biāo)簽中
</template>
我也是default的內(nèi)容 // 默認(rèn)算default模板內(nèi)容
</todo-item>
等價(jià)于
<todo-item>
<template v-slot:default>
我是default的內(nèi)容 我也是default的內(nèi)容
</template>
<template v-slot:test>
我會(huì)渲染到name=test的slot標(biāo)簽中
</template>
</todo-item>
default模板的內(nèi)容必定會(huì)渲染到defalut插槽中暖庄,所以聊替,通過子組件情形1能得出渲染結(jié)果,也可以得出一個(gè)結(jié)論:
②.子組件中沒有指定name屬性的slot標(biāo)簽培廓,默認(rèn)都是default插槽惹悄,即
<div>
<slot></slot>
</div>
等價(jià)于
<div>
<slot name="default"></slot>
</div>
最后還需要注意,模板和插槽的對(duì)應(yīng)關(guān)系是1對(duì)多的關(guān)系肩钠。即同名模板只能有一個(gè)泣港,但是同名插槽可以有無數(shù)個(gè),會(huì)同時(shí)渲染
以上內(nèi)容涵蓋了9成的插槽用法价匠,足以滿足日常使用当纱。下面將要對(duì)插槽作用域問題展開講解
6.模板內(nèi)容的作用域和插槽內(nèi)容的作用域
很簡(jiǎn)單
1.模板內(nèi)容一般都是在父組件,所以模板內(nèi)容的作用域自然是父組件的作用域踩窖,父組件的動(dòng)態(tài)內(nèi)容基本上取自父組件的變量或函數(shù)坡氯,但是有特殊情況可以讀取到子組件傳出來的值,第3點(diǎn)會(huì)講毙石。
2.同理廉沮,插槽一般都是在子組件,所以作用域自然在子組件徐矩,比如子組件插槽中放入了動(dòng)態(tài)內(nèi)容作為默認(rèn)值滞时,該動(dòng)態(tài)內(nèi)容必定取值于子組件的變量,也只能讀取到子組件的變量和函數(shù)
3.特殊情況滤灯,父組件可以用子組件傳出來的值坪稽,這個(gè)時(shí)候會(huì)有寫法上的變化:
子組件
<script>
export default {
data() {
return {
content: '我是子組件',
show: true
}
}
}
</script>
<template>
<div>
<slot name="default" :todo-item-content="content" :show="show"></slot> // 通過格式:自定義屬性名="變量名"將值傳出
</div>
</template>
<style>
</style>
父組件正常調(diào)用
<todo-item>
<template v-slot:default="props"> //這里的props是我們自己定義的名稱鳞骤,你可以自己起任意名窒百,它是一個(gè)對(duì)象,包含子組件傳過來的所有值
<div> // 這里需要注意的是豫尽,子組件用橫杠屬性名傳過來的值篙梢,在調(diào)用的時(shí)候要用駝峰名調(diào)用
{{props.todoListContent}}
</div>
<div> // 不是橫杠屬性名傳過來的值可以直接調(diào)用
{{props.show}}
</div>
</template>
</todo-item>
父組件解構(gòu)對(duì)象調(diào)用
<todo-item>
<template v-slot:default="{todoListContent,show}">
<div>
{{todoListContent}}
</div>
<div>
{{show}}
</div>
</template>
</todo-item>
渲染結(jié)果
<div>
我是子組件
</div>
<div>
true
</div>
7.v-slot指令縮寫
v-slot指令可以變成縮寫的寫法美旧,類似v-bind縮寫為:渤滞,v-on縮寫為@贬墩,v-slot可以縮寫為#
例如
<template v-slot:default>
</template>
<template v-slot:test1>
</template>
<template v-slot:test2>
</template>
等價(jià)于
<template #default>
</template>
<template #test1>
</template>
<template #test2>
</template>
8.default模板一種特殊的接受子組件插槽傳值的寫法(結(jié)合第6點(diǎn)的例子)
<todo-item #default="{todoListContent,show}">
<div>
{{todoListContent}}
</div>
<div>
{{show}}
</div>
</todo-item>
這里出現(xiàn)了v-slot指令直接綁定在子組件標(biāo)簽名上的情況妄呕,使用場(chǎng)景是陶舞,當(dāng)前模板只有一個(gè)default模板,并且需要獲取子組件傳來的值時(shí)绪励,才能這樣使用肿孵。
不接受傳值的情況,會(huì)報(bào)錯(cuò)
<todo-item #default> // 報(bào)錯(cuò)疏魏,必須是接受傳值的寫法停做,即#default="xxx.."
<div>
我是模板
</div>
</todo-item>
非default模板,也會(huì)報(bào)錯(cuò)
子組件
<script>
export default {
data() {
return {
content: '我是子組件'蠢护,
show: true
}
}
}
</script>
<template>
<div> // 這里是test插槽
<slot name="test" :todo-item-content="content" :show="show"></slot>
</div>
</template>
<style>
</style>
父組件
// 這里是test模板雅宾,是具名模板的寫法,會(huì)報(bào)錯(cuò)葵硕,因?yàn)檫@種寫法只支持default模板
<todo-item #test="{todoListContent眉抬,show}">
<div>
{{todoListContent}}
</div>
<div>
{{show}}
</div>
</todo-item>
除了default模板外,還存在其他模板時(shí)懈凹,也會(huì)報(bào)錯(cuò)
<todo-item #default="{todoListContent蜀变,show}"> // default模板
<div>
{{todoListContent}}
</div>
<div>
{{show}}
</div>
<template v-slot:test> // test模板 此處將不生效,并且會(huì)拋出警告
</template>
</todo-item>
結(jié)語(yǔ):
以上基本總結(jié)了插槽的所有用法介评,其中第5點(diǎn)和第8點(diǎn)的特殊情況都是針對(duì)default模板的库北,這一點(diǎn)一定要分清楚。
還有1點(diǎn)很關(guān)鍵的知識(shí)们陆,即default模板和插槽不算是具名模板和插槽寒瓦,第8點(diǎn)的非default模板會(huì)報(bào)錯(cuò)的原因,即該特殊情況不支持具名模板和插槽坪仇。但是default模板和插槽在平時(shí)寫的時(shí)候可以用具名模板和插槽的寫法杂腰,也可以用省略的寫法,即第5點(diǎn)描述的情況椅文。