Vue3中slot插槽基本使用
使用Vue的小伙伴相信你一定使用過插槽,如果你沒有用過,那說明你的項(xiàng)目可能不是特別復(fù)雜。插槽(slot)可以說在一個(gè)Vue項(xiàng)目里面處處都有它的身影,比如我們使用一些UI組件庫的時(shí)候,我們通??梢允褂貌宀蹃碜远x我們的內(nèi)容。
1.插槽基本使用
插槽的用途就和它的名字一樣:有一個(gè)缺槽,我們可以插入一些東西。
插槽slot通常用于兩個(gè)父子組件之間,最常見的應(yīng)用就是我們使用一些UI組件庫中的彈窗組件時(shí),彈窗組件的內(nèi)容是可以讓我們自定義的,這就是使用了插槽的原理。
我們?cè)陧?xiàng)目中新建一個(gè)child.vue文件,用來當(dāng)作子組件,它的代碼也非常的簡(jiǎn)單。
child.vue 代碼如下:
<template>
<div class="child-box">
<p>我是子組件</p>
<!-- 插槽 -->
<slot></slot>
</div>
</template>
<style>
.child-box {
display: flex;
flex-direction: column;
align-items: center;
}
</style>然后我們直接在App.vue引用該子組件,代碼如下:
<template> <img alt="Vue logo" src="./assets/logo.png" /> <child></child> </template> <script setup lang="ts"> import Child from "./child.vue"; </script>
輸出結(jié)果:

child子組件代碼非常的簡(jiǎn)單,唯一不同的里面我們添加了一對(duì)<slot></slot>標(biāo)簽,這就是插槽標(biāo)簽。這對(duì)標(biāo)簽就好比我們?cè)?code>child組件內(nèi)部挖了一個(gè)槽出來,我們接下來就可以往這個(gè)槽里面放置一些內(nèi)容。
那么我們?nèi)绾瓮@個(gè)槽里面放置內(nèi)容呢?
我們?cè)?code>App.vue里面通過一對(duì)閉合標(biāo)簽<child></child>調(diào)用了子組件,我們都知道HTML標(biāo)簽之間是可以插入內(nèi)容的,雖然child不是HTML自帶的標(biāo)簽,但是它卻有著類似的特征,比如我們往<child></child>之間插入一點(diǎn)內(nèi)容,代碼如下:
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<child>
<div>小豬課堂</div>
</child>
</template>輸出結(jié)果:

我們發(fā)現(xiàn)在<child></child>標(biāo)簽之間插入的內(nèi)容被渲染出來了,那么這是為何呢?
前面我們說slot就是挖了一個(gè)槽出來,可以放置東西,這里我們?cè)诟附M件中添加的div便就是我們要添加的東西,子組件中slot標(biāo)簽被替換為了我們插入的div元素。這就是插槽的最基本使用。
結(jié)論:
為了更好理解插槽,簡(jiǎn)單總結(jié)為以下幾點(diǎn):
slot是Vue3中的內(nèi)置標(biāo)簽。slot相當(dāng)于給子組件挖出了一個(gè)槽,可以用來填充內(nèi)容。- 父組件中調(diào)用子組件時(shí),子組件標(biāo)簽之間的內(nèi)容元素就是要放置的內(nèi)容,它會(huì)把
slot標(biāo)簽替換掉。
最簡(jiǎn)單的理解:我們的使用U盤需要將U盤插入USB口中,此時(shí)USB口就是插槽,U盤就是插口。在Vue中,<slot></slot>就是電腦插槽,父組件的內(nèi)容就可以理解為U盤插口。
2.插槽默認(rèn)內(nèi)容
我們通常將插槽比作一個(gè)占位符,有內(nèi)容進(jìn)來時(shí),自動(dòng)把slot給替換掉。但是,如果沒有內(nèi)容進(jìn)來時(shí),那么應(yīng)該渲染什么呢?
在很多場(chǎng)景下都會(huì)有這種需求,比如UI組件庫中的彈窗,如果我們沒有傳入彈窗的頭部或者底部,那么彈窗便會(huì)有默認(rèn)的樣式效果,這里就用到了slot的默認(rèn)內(nèi)容功能。
修改一下 child.vue 代碼:
<template>
<div class="child-box">
<p>我是子組件</p>
<!-- 插槽 -->
<slot>
<p>我是默認(rèn)內(nèi)容</p>
</slot>
</div>
</template>當(dāng)我們的App.vue沒有向child組件傳入內(nèi)容時(shí),會(huì)是什么效果呢?
App.vue 代碼如下:
<template> <img alt="Vue logo" src="./assets/logo.png" /> <child></child> </template>
輸出結(jié)果:

可以看到子組件同樣渲染了內(nèi)容,而且就是slot標(biāo)簽內(nèi)的內(nèi)容。那么我們我們往child組件傳入一點(diǎn)內(nèi)容會(huì)是什么效果呢?
App.vue 代碼如下:
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<child>
<div>{{ message }}</div>
</child>
</template>
<script setup lang="ts">
import { ref } from "vue";
import Child from "./child.vue";
const message = ref("小豬課堂");
</script>輸出結(jié)果:

可以看到此時(shí)頁面上渲染的App.vue父組件傳入的內(nèi)容了。
總結(jié):
從上面例子不難看出,slot 標(biāo)簽內(nèi)的內(nèi)容就是默認(rèn)內(nèi)容,也就是當(dāng)父組件沒有傳遞給子組件內(nèi)容時(shí),子組件就會(huì)默認(rèn)渲染 slot 內(nèi)部的內(nèi)容,但是 slot 標(biāo)簽是不會(huì)渲染出來的。
3.具名插槽
很多時(shí)候我們子組件中都不止只有一個(gè)slot,比如彈窗組件,我們可能允許調(diào)用者同時(shí)傳入header、content、footer等等,這個(gè)時(shí)候如果子組件中只有一個(gè)slot,那么這么多內(nèi)容該如何區(qū)分,或者說該如何渲染呢?
3.1 基本使用
這個(gè)時(shí)候?yàn)榱藚^(qū)分插槽與內(nèi)容的對(duì)應(yīng)關(guān)系,我們可以分別給slot和內(nèi)容都加上一個(gè)名字,插入插槽的時(shí)候大家按照名字區(qū)分好就可以了。
我們給child組件添加上多個(gè)slot,并且給每個(gè)slot取上一個(gè)名字。
代碼如下:
<template>
<div class="child-box">
<p>我是子組件</p>
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>上段代碼中我們添加了3個(gè)slot插槽,并且給其中兩個(gè)slot標(biāo)簽添加了一個(gè)name屬性,也就是每個(gè)插槽的名字。需要注意的是,上段代碼中有一個(gè)插槽我們沒有添加name屬性,這個(gè)時(shí)候Vue會(huì)隱式的將這個(gè)插槽命名為“default”,接下來就是我們父組件App.vue添加內(nèi)容了。
代碼如下:
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<child>
<template v-slot:header>
<div>我是 header:{{ message }}</div>
</template>
<div>我沒有名字:{{ message }}</div>
<template v-slot:footer>
<div>我是 footer:{{ message }}</div>
</template>
</child>
</template>輸出結(jié)果:

既然slot有了名字,那么我們?cè)诟附M件中傳入內(nèi)容時(shí)就要和名字關(guān)系對(duì)應(yīng)起來,我們采用v-slot:header指令的形式找到對(duì)應(yīng)的插槽,需要注意的是該指令需要作用在template元素上。從上圖可以看出,我們傳入的內(nèi)容都渲染到了對(duì)應(yīng)的插槽內(nèi),沒有命名的插槽渲染了我們傳入的未添加指令的內(nèi)容。
3.2 簡(jiǎn)寫
在Vue中,很多指令都有簡(jiǎn)寫形式,v-slot:name指令也有簡(jiǎn)寫形式,比如看我們下面的示例。
原寫法:
<template v-slot:footer> </template>
簡(jiǎn)寫法:
<template #footer> </template>
接下來我們?cè)诮栌霉倬W(wǎng)的一張圖來清楚的了解具名插槽中的父子組件關(guān)系。

其中BaseLayout為一個(gè)子組件,就和我們child組件一樣。
3.3 默認(rèn)插槽與具名插槽混用
當(dāng)一個(gè)子組件中既有具名插槽,又有默認(rèn)插槽時(shí),該如何渲染呢?
前面我們說默認(rèn)插槽會(huì)被隱式的命名為default,所以我們傳入內(nèi)容時(shí)可以將插槽名字改為defalut即可。
修改 child 組件:
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<child>
<template v-slot:header>
<div>我是 header:{{ message }}</div>
</template>
<template v-slot:default>
<div>我沒有名字:{{ message }}</div>
<div>我沒有名字:{{ message }}</div>
<div>我沒有名字:{{ message }}</div>
</template>
<template v-slot:footer>
<div>我是 footer:{{ message }}</div>
</template>
</child>
</template>雖然說子組件中有一個(gè)slot沒有取名字,但是默認(rèn)可以用default來代表它,就好比人剛出生的時(shí)候沒有名字,但是他又一個(gè)默認(rèn)屬性:“人”。
當(dāng)然,既然大家都是默認(rèn)的,在父組件中你也可以不用名字,這個(gè)時(shí)候內(nèi)容會(huì)默認(rèn)傳入到未命名插槽中去。
代碼如下:
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<child>
<template v-slot:header>
<div>我是 header:{{ message }}</div>
</template>
<div>我沒有名字:{{ message }}</div>
<div>我沒有名字:{{ message }}</div>
<div>我沒有名字:{{ message }}</div>
<template v-slot:footer>
<div>我是 footer:{{ message }}</div>
</template>
</child>
</template>輸出結(jié)果:

4.動(dòng)態(tài)插槽名
前面我們給插槽命名的時(shí)候都是直接寫死的,其實(shí)我們有時(shí)候可以動(dòng)態(tài)給插槽命名的,以滿足更多的業(yè)務(wù)場(chǎng)景。
代碼如下:
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
<!-- 縮寫為 -->
<template #[dynamicSlotName]>
...
</template>
</base-layout>上段代碼就是在父組件中采用動(dòng)態(tài)插槽名傳入內(nèi)容的示例。
5.插槽作用域問題
我們仔細(xì)思考插槽的使用,會(huì)發(fā)現(xiàn)這有一點(diǎn)類似于父子組件傳遞,只不過插槽傳遞的是模板內(nèi)容罷了。那么涉及到傳值,就會(huì)有一個(gè)作用域的問題,我們回顧一下App.vue中的一段代碼。
代碼如下:
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<child>
<div>{{ message }}</div>
</child>
</template>
<script setup lang="ts">
import { ref } from "vue";
import Child from "./child.vue";
const message = ref("小豬課堂");
</script>上段代碼中message是我們?cè)诟附M件中定義的數(shù)據(jù),但是在我們的子組件child中渲染了出來,說明子組件中的插槽是可以訪問到父組件中的數(shù)據(jù)作用域的,但是反過來是不行的,因?yàn)槲覀儫o法通過插槽拿到子組件的數(shù)據(jù)。
總結(jié):
所以我們這里總結(jié)為兩點(diǎn)
- 插槽內(nèi)容可以訪問到父組件的數(shù)據(jù)作用域,就好比上述中的
message是父組件的。 - 插槽內(nèi)容無法訪問到子組件的數(shù)據(jù),就好比上述
App.vue中的插槽內(nèi)容拿不到子組件child的數(shù)據(jù)。
6.作用域插槽
前一節(jié)我們說父組件中的插槽內(nèi)容是無法訪問到子組件中的數(shù)據(jù)的,但是,萬一我們有需求就是需要在插槽內(nèi)容中獲取子組件數(shù)據(jù)怎么辦呢?
Vue3給我們提供了方法,使用起來也比較簡(jiǎn)單。
6.1 默認(rèn)插槽作用域傳值
我們先來演示默認(rèn)插槽如何獲取子組件的數(shù)據(jù)。
child.vue 代碼如下:
<template>
<div class="child-box">
<p>我是子組件</p>
<slot text="我是子組件小豬課堂" :count="1"></slot>
</div>
</template>App.vue 組件代碼:
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<child v-slot="slotProps">
<div>{{ slotProps.text }}---{{ slotProps.count }}</div>
</child>
</template>輸出結(jié)果:

上段代碼中我們?cè)谧咏M件中slot標(biāo)簽上添加了一些自定義屬性,屬性值就是我們想要傳遞給父組件的一些內(nèi)容。在父組件App.vue中通過v-slot="slotProps"等形式接收子組件傳毒過來的數(shù)據(jù),slotProps的名字是可以任意取的,它是一個(gè)對(duì)象,包含了所有傳遞過來的數(shù)據(jù)。
需要注意的是,子組件傳遞過來的數(shù)據(jù)只能在子組件這個(gè)標(biāo)簽內(nèi)使用。
解構(gòu)寫法:
我們都知道對(duì)象是可以解構(gòu)的,所以我們?cè)诟附M件中還可以直接使用解構(gòu)的寫法來獲取數(shù)據(jù)。
代碼如下:
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<child v-slot="{ text, count }">
<div>{{ text }}---{{ count }}</div>
</child>
</template>6.2 具名插槽作用域傳值
具名插槽作用域之間的傳遞其實(shí)默認(rèn)插槽作用域傳值原理是一樣的,只不過寫法不一樣罷了。
child.vue 代碼如下:
<template>
<div class="child-box">
<p>我是子組件</p>
<slot name="header" text="我是子組件小豬課堂" :count="1"></slot>
</div>
</template>App.vue 代碼如下:
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<child>
<template #header="{ text, count }">
<div>{{ text }}---{{ count }}</div>
</template>
</child>
</template>
上段代碼中我們給slot添加了一個(gè)name,在父組件中接收數(shù)據(jù)的時(shí)候不在采用v-slot=""形式了,而是直接再插槽內(nèi)容上采用#header=""形式,當(dāng)時(shí)這是簡(jiǎn)寫形式,你也可以寫為:v-slot:header=""
總結(jié)
插槽的作用非常廣泛,學(xué)好插槽對(duì)我們的項(xiàng)目開發(fā)有著非常大的幫助,當(dāng)然,想要非常優(yōu)雅的使用插槽,還是需要費(fèi)一些功夫的。這里可以推薦大家去看一看element組件庫中的table的使用,看看它是如何使用插槽的,如何優(yōu)雅的將表格組件中的數(shù)據(jù)共享給父組件的。
到此這篇關(guān)于Vue3中slot插槽使用方式的文章就介紹到這了,更多相關(guān)Vue3插槽使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue動(dòng)態(tài)加載圖片在跨域時(shí)無法顯示的問題及解決方法
這篇文章主要介紹了解決VUE動(dòng)態(tài)加載圖片在跨域時(shí)無法顯示的問題,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03
Vue通過字符串關(guān)鍵字符實(shí)現(xiàn)動(dòng)態(tài)渲染input輸入框
這篇文章主要為大家詳細(xì)介紹了Vue如何通過字符串關(guān)鍵字符實(shí)現(xiàn)動(dòng)態(tài)渲染input輸入框。文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-12-12
Vue3?<script?setup?lang=“ts“>?的基本使用
<script setup>?是在單文件組件 (SFC) 中使用?composition api?的編譯時(shí)語法糖,本文主要講解<script setup>?與?TypeScript?的基本使用,感興趣的朋友跟隨小編一起看看吧2022-12-12
uniapp微信小程序使用webview嵌套u(yù)niappH5并實(shí)現(xiàn)通信詳細(xì)步驟
在開發(fā)微信小程序的時(shí)候,我們有時(shí)候會(huì)遇到將H5頁面嵌入到小程序頁面中的情況,這篇文章主要給大家介紹了關(guān)于uniapp微信小程序使用webview嵌套u(yù)niappH5并實(shí)現(xiàn)通信的詳細(xì)步驟,需要的朋友可以參考下2024-05-05

