Vue3中slot插槽基本使用
使用Vue的小伙伴相信你一定使用過插槽,如果你沒有用過,那說明你的項目可能不是特別復雜。插槽(slot)可以說在一個Vue項目里面處處都有它的身影,比如我們使用一些UI組件庫的時候,我們通??梢允褂貌宀蹃碜远x我們的內(nèi)容。
1.插槽基本使用
插槽的用途就和它的名字一樣:有一個缺槽,我們可以插入一些東西。
插槽slot通常用于兩個父子組件之間,最常見的應用就是我們使用一些UI組件庫中的彈窗組件時,彈窗組件的內(nèi)容是可以讓我們自定義的,這就是使用了插槽的原理。
我們在項目中新建一個child.vue文件,用來當作子組件,它的代碼也非常的簡單。
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>
輸出結果:

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

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

可以看到子組件同樣渲染了內(nèi)容,而且就是slot標簽內(nèi)的內(nèi)容。那么我們我們往child組件傳入一點內(nèi)容會是什么效果呢?
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>輸出結果:

可以看到此時頁面上渲染的App.vue父組件傳入的內(nèi)容了。
總結:
從上面例子不難看出,slot 標簽內(nèi)的內(nèi)容就是默認內(nèi)容,也就是當父組件沒有傳遞給子組件內(nèi)容時,子組件就會默認渲染 slot 內(nèi)部的內(nèi)容,但是 slot 標簽是不會渲染出來的。
3.具名插槽
很多時候我們子組件中都不止只有一個slot,比如彈窗組件,我們可能允許調(diào)用者同時傳入header、content、footer等等,這個時候如果子組件中只有一個slot,那么這么多內(nèi)容該如何區(qū)分,或者說該如何渲染呢?
3.1 基本使用
這個時候為了區(qū)分插槽與內(nèi)容的對應關系,我們可以分別給slot和內(nèi)容都加上一個名字,插入插槽的時候大家按照名字區(qū)分好就可以了。
我們給child組件添加上多個slot,并且給每個slot取上一個名字。
代碼如下:
<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個slot插槽,并且給其中兩個slot標簽添加了一個name屬性,也就是每個插槽的名字。需要注意的是,上段代碼中有一個插槽我們沒有添加name屬性,這個時候Vue會隱式的將這個插槽命名為“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>輸出結果:

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

其中BaseLayout為一個子組件,就和我們child組件一樣。
3.3 默認插槽與具名插槽混用
當一個子組件中既有具名插槽,又有默認插槽時,該如何渲染呢?
前面我們說默認插槽會被隱式的命名為default,所以我們傳入內(nèi)容時可以將插槽名字改為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>雖然說子組件中有一個slot沒有取名字,但是默認可以用default來代表它,就好比人剛出生的時候沒有名字,但是他又一個默認屬性:“人”。
當然,既然大家都是默認的,在父組件中你也可以不用名字,這個時候內(nèi)容會默認傳入到未命名插槽中去。
代碼如下:
<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>輸出結果:

4.動態(tài)插槽名
前面我們給插槽命名的時候都是直接寫死的,其實我們有時候可以動態(tài)給插槽命名的,以滿足更多的業(yè)務場景。
代碼如下:
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
<!-- 縮寫為 -->
<template #[dynamicSlotName]>
...
</template>
</base-layout>上段代碼就是在父組件中采用動態(tài)插槽名傳入內(nèi)容的示例。
5.插槽作用域問題
我們仔細思考插槽的使用,會發(fā)現(xiàn)這有一點類似于父子組件傳遞,只不過插槽傳遞的是模板內(nèi)容罷了。那么涉及到傳值,就會有一個作用域的問題,我們回顧一下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是我們在父組件中定義的數(shù)據(jù),但是在我們的子組件child中渲染了出來,說明子組件中的插槽是可以訪問到父組件中的數(shù)據(jù)作用域的,但是反過來是不行的,因為我們無法通過插槽拿到子組件的數(shù)據(jù)。
總結:
所以我們這里總結為兩點
- 插槽內(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給我們提供了方法,使用起來也比較簡單。
6.1 默認插槽作用域傳值
我們先來演示默認插槽如何獲取子組件的數(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>輸出結果:

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

