1. 具名插槽
1.1 沒有使用具名插槽的問題
有的時候我們在使用子組件時,在子組件模板上不同的位置插入不同的內(nèi)容, 只有一個插槽顯然沒發(fā)滿足我們的需求,看示例:
需求如下:
- 子組件是一篇文章的結(jié)構(gòu)
- 父組件在調(diào)用子組件是給文章插入標題,正文,時間信息
示例代碼如下:
<div id="app">
<!-- 使用組件 -->
<my-child >
<h2>這是一篇介紹vue插槽的文章</h2>
<p>這是文章的第一段</p>
<p>這是文章的第二段內(nèi)容</p>
<p>這是文章的第三段內(nèi)容</p>
<span>2020年5月1日</span>
</my-child>
</div>
<!-- 組件模板 -->
<template id="mychild">
<div class="article">
<div class="title">
<slot></slot>
</div>
<div class="contont">
<slot></slot>
</div>
<div class="time">
<slot></slot>
</div>
</div>
</template>
<script>
// 組件選項對象
let MyChild = {
template: `#mychild`
};
// 實例中注冊組件
const vm = new Vue({
el:"#app",
components: {
MyChild
}
})
</script>
結(jié)果:
示例結(jié)果說明:
- 通過示例結(jié)果發(fā)現(xiàn)和我們想的天差地別,此時每一個插槽都插入了所有的內(nèi)容, 顯然不符合預期
- 那么我們怎樣才能將分發(fā)的內(nèi)容指定到每一個具體的插槽上呢.
這個時候我們就需要給每個插槽指定名字
1.2 使用具名插槽和默認插槽
<slot>
元素可以用一個特殊的特性 name
來進一步配置如何分發(fā)內(nèi)容。多個插槽可以有不同的名字曲秉。具名插槽將匹配內(nèi)容片段中有對應 slot
特性的元素镜悉。
未使用name
屬性的slot
插槽被稱匿名插槽
, 也可以叫做默認插槽
. 我們在子組件中仍然可以有一個匿名插槽谍珊,作為找不到匹配的內(nèi)容片段的備用插槽。如果沒有默認插槽蛤铜,這些找不到匹配的內(nèi)容片段將被拋棄。
使用具名操作重寫上面的示例:
<div id="app">
<!-- 使用組件 -->
<my-child >
<h2 slot="title">這是一篇介紹vue插槽的文章</h2>
<p>這是文章的第一段</p>
<p>這是文章的第二段內(nèi)容</p>
<p>這是文章的第三段內(nèi)容</p>
<span slot="time">2020年5月1日</span>
</my-child>
</div>
<!-- 組件模板 -->
<template id="mychild">
<div class="article">
<div class="title">
<slot name="title">這里是標題內(nèi)容的插槽</slot>
</div>
<div class="contont">
<slot>這里是默認插槽</slot>
</div>
<div class="time">
<slot name="time">這里是時間的插槽</slot>
</div>
</div>
</template>
<script>
// 組件選項對象
let MyChild = {
template: `#mychild`
};
// 實例中注冊組件
const vm = new Vue({
el:"#app",
components: {
MyChild
}
})
</script>
結(jié)果:
此時我們就會發(fā)現(xiàn),分發(fā)的內(nèi)容以及正常插入到對應的插槽上了
通過上面的例子我們就知道了,slot
如果沒有顯示的使用name
屬性指定插槽的名字,那么slot默認有個名字default
,默認插槽,如果在分發(fā)內(nèi)容時,沒有指定插槽,所有的內(nèi)容都將默認插到默認插槽上
2. 作用域插槽
2.1 作用插槽的理解和使用
通過學習我們知道,插槽的內(nèi)容最后是在子組件模板上渲染的, 那么就會在有得時候需要在分發(fā)的內(nèi)容中使用子組件中才有的數(shù)據(jù),怎么辦呢. 這個時候就要用到作用域插槽了
作用域插槽是一種特殊類型的插槽迷雪,用作一個 (能被傳遞數(shù)據(jù)的) 可重用模板载矿,來代替已經(jīng)渲染好的元素垄潮。
簡而言之,就是利用slot
標簽將子組件的數(shù)據(jù)傳遞到分發(fā)內(nèi)中上,就像prop
傳遞數(shù)據(jù)給組件一樣
在父級中,具有特殊特性 slot-scope
的 <template>
元素必須存在闷盔,表示它是作用域插槽的模板弯洗。slot-scope
的值將被用作一個臨時變量名,此變量接收從子組件傳遞過來的 props
對象:
示例:
<div id="app">
<!-- 使用組件 -->
<my-child >
<template slot-scope="props">
<button>{{ props.text }}</button>
</template>
</my-child>
</div>
<!-- 組件模板 -->
<template id="mychild">
<div>
<slot :text="text"></slot>
</div>
</template>
<script>
// 組件選項對象
let MyChild = {
template: `#mychild`,
data(){
return {
text: "提交"
}
}
};
// 實例中注冊組件
const vm = new Vue({
el:"#app",
components: {
MyChild
}
})
</script>
在 2.5.0+逢勾,
slot-scope
能被用在任意元素或組件中而不再局限于<template>
牡整。
也就意味著可以如下寫法
<div id="app">
<!-- 使用組件 -->
<my-child >
<button slot-scope="props">{{ props.text }}</button>
</my-child>
</div>
顯示結(jié)果
2.2 作用域插槽也可以使用解構(gòu)寫法
<div id="app">
<!-- 使用組件 -->
<my-child >
<button slot-scope="{text}">{{ text }}</button>
</my-child>
</div>
很遺憾的告訴你, 具名插槽和作用域插槽的用法在未來即將被廢棄?
What? 那么我們怎么處理具名插槽和作用域插槽取消后留下的問題呢? 不用擔心,往下看.
3. v-slot指令
v-slot
指令自 Vue 2.6.0 起被引入,提供更好的支持slot
和slot-scope
attribute 的 API 替代方案溺拱。v-slot
完整的由來參見這份 RFC逃贝。在接下來所有的 2.x 版本中slot
和slot-scope
attribute 仍會被支持,但已經(jīng)被官方廢棄且不會出現(xiàn)在 Vue 3 中迫摔。
3.1 使用v-slot處理具名插槽的問題
在向具名插槽提供內(nèi)容的時候沐扳,我們可以在一個 <template>
元素上使用 v-slot
指令,并以 v-slot
的參數(shù)的形式提供其名稱:
<div id="app">
<!-- 使用組件 -->
<my-child >
<template v-slot:title>
<h2>這是一篇介紹vue插槽的文章</h2>
</template>
<p>這是文章的第一段</p>
<p>這是文章的第二段內(nèi)容</p>
<p>這是文章的第三段內(nèi)容</p>
<template v-slot:time>
<span>2020年5月1日</span>
</template>
</my-child>
</div>
<!-- 組件模板 -->
<template id="mychild">
<div class="article">
<div class="title">
<slot name="title">這里是標題內(nèi)容的插槽</slot>
</div>
<div class="contont">
<slot>這里是默認插槽</slot>
</div>
<div class="time">
<slot name="time">這里是時間的插槽</slot>
</div>
</div>
</template>
<script>
// 組件選項對象
let MyChild = {
template: `#mychild`
};
// 實例中注冊組件
const vm = new Vue({
el:"#app",
components: {
MyChild
}
})
</script>
顯示結(jié)果:
現(xiàn)在 <template>
元素中的所有內(nèi)容都將會被傳入相應的插槽句占。任何沒有被包裹在帶有 v-slot
的 <template>
中的內(nèi)容都會被視為默認插槽的內(nèi)容迫皱。
如果你希望更明確一些,仍然可以在一個 <template>
中包裹默認插槽的內(nèi)容:
<div id="app">
<!-- 使用組件 -->
<my-child >
<template v-slot:title>
<h2>這是一篇介紹vue插槽的文章</h2>
</template>
<template v-slot:default>
<p>這是文章的第一段</p>
<p>這是文章的第二段內(nèi)容</p>
<p>這是文章的第三段內(nèi)容</p>
</template>
<template v-slot:time>
<span>2020年5月1日</span>
</template>
</my-child>
</div>
注意 v-slot 只能添加在 <template> 上
3.2 使用v-slot處理作用域插槽的問題
綁定在 <slot>
元素上的 attribute 被稱為插槽 prop∠街冢現(xiàn)在在父級作用域中,我們可以使用帶值的 v-slot
來定義我們提供的插槽 prop 的名字:
<div id="app">
<!-- 使用組件 -->
<my-child >
<template v-slot:default="props">
<button>{{ props.text }}</button>
</template>
</my-child>
</div>
<!-- 組件模板 -->
<template id="mychild">
<div>
<slot :text="text"></slot>
</div>
</template>
<script>
// 組件選項對象
let MyChild = {
template: `#mychild`,
data(){
return {
text: "提交"
}
}
};
// 實例中注冊組件
const vm = new Vue({
el:"#app",
components: {
MyChild
}
})
</script>
顯示結(jié)果
3.3 作用域插槽的特殊處理
在上述情況下和敬,當被提供的內(nèi)容只有默認插槽時凹炸,組件的標簽才可以被當作插槽的模板來使用。這樣我們就可以把 v-slot
直接用在組件上:
<div id="app">
<!-- 使用組件 -->
<my-child v-slot:default="props">
<button>{{ props.text }}</button>
</my-child>
</div>
這種寫法還可以更簡單昼弟。就像假定未指明的內(nèi)容對應默認插槽一樣啤它,不帶參數(shù)的 v-slot
被假定對應默認插槽:
<div id="app">
<!-- 使用組件 -->
<my-child v-slot="props">
<button>{{ props.text }}</button>
</my-child>
</div>
這用這種簡單語法的情況就是在組件中只有一個默認插槽,一但有多個插槽,請使用完整的語法
4. 動態(tài)插槽
2.6.0 新增
動態(tài)指令參數(shù)也可以用在 v-slot
上,來定義動態(tài)的插槽名:
還是以我們剛才文章的那個多插槽為例;
<div id="app">
<!-- 使用組件 -->
<my-child >
<template v-slot:[head]>
<h2>這是一篇介紹vue插槽的文章</h2>
</template>
<p>這是文章的第一段</p>
<p>這是文章的第二段內(nèi)容</p>
<p>這是文章的第三段內(nèi)容</p>
<template v-slot:[food]>
<span>2020年5月1日</span>
</template>
</my-child>
</div>
<!-- 組件模板 -->
<template id="mychild">
<div class="article">
<div class="title">
<slot name="title">這里是標題內(nèi)容的插槽</slot>
</div>
<div class="contont">
<slot>這里是默認插槽</slot>
</div>
<div class="time">
<slot name="time">這里是時間的插槽</slot>
</div>
</div>
</template>
<script>
// 組件選項對象
let MyChild = {
template: `#mychild`
};
// 實例中注冊組件
const vm = new Vue({
el:"#app",
data:{
head:"title",
food:"time"
},
components: {
MyChild
}
})
</script>
此時template 標簽上的v-solt指令參數(shù)是一個中括號, 中括號里的值將是一個變量,為當前父組件的數(shù)據(jù)
5. 具名插槽的縮寫
2.6.0 新增
跟 v-on
和 v-bind
一樣,v-slot
也有縮寫变骡,即把參數(shù)之前的所有內(nèi)容 (v-slot:
) 替換為字符 #
离赫。例如 v-slot:header
可以被重寫為 #header
:
<div id="app">
<!-- 使用組件 -->
<my-child >
<template #title>
<h2>這是一篇介紹vue插槽的文章</h2>
</template>
<p>這是文章的第一段</p>
<p>這是文章的第二段內(nèi)容</p>
<p>這是文章的第三段內(nèi)容</p>
<template #time>
<span>2020年5月1日</span>
</template>
</my-child>
</div>
然而,和其它指令一樣塌碌,該縮寫只在其有參數(shù)的時候才可用渊胸。這意味著以下語法是無效的:
<my-child >
<!-- 這種寫法無效 -->
<template #="props">
<h2>這是一篇介紹vue插槽的文章</h2>
</template>
</my-child>
如果你希望使用縮寫的話,你必須始終以明確插槽名取而代之:
<my-child >
<!-- 這種寫法有效,因為有指令參數(shù) -->
<template #deatule="props">
<h2>這是一篇介紹vue插槽的文章</h2>
</template>
</my-child>