Vue3中slot插槽基本使用
使用Vue
的小伙伴相信你一定使用過插槽,如果你沒有用過,那說明你的項目可能不是特別復雜。插槽(slot)可以說在一個Vue
項目里面處處都有它的身影,比如我們使用一些UI
組件庫的時候,我們通常可以使用插槽來自定義我們的內容。
1.插槽基本使用
插槽的用途就和它的名字一樣:有一個缺槽,我們可以插入一些東西。
插槽slot
通常用于兩個父子組件之間,最常見的應用就是我們使用一些UI
組件庫中的彈窗組件時,彈窗組件的內容是可以讓我們自定義的,這就是使用了插槽的原理。
我們在項目中新建一個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
組件內部挖了一個槽出來,我們接下來就可以往這個槽里面放置一些內容。
那么我們如何往這個槽里面放置內容呢?
我們在App.vue
里面通過一對閉合標簽<child></child>
調用了子組件,我們都知道HTML
標簽之間是可以插入內容的,雖然child
不是HTML
自帶的標簽,但是它卻有著類似的特征,比如我們往<child></child>
之間插入一點內容,代碼如下:
<template> <img alt="Vue logo" src="./assets/logo.png" /> <child> <div>小豬課堂</div> </child> </template>
輸出結果:
我們發(fā)現(xiàn)在<child></child>
標簽之間插入的內容被渲染出來了,那么這是為何呢?
前面我們說slot
就是挖了一個槽出來,可以放置東西,這里我們在父組件中添加的div
便就是我們要添加的東西,子組件中slot
標簽被替換為了我們插入的div
元素。這就是插槽的最基本使用。
結論:
為了更好理解插槽,簡單總結為以下幾點:
slot
是Vue3
中的內置標簽。slot
相當于給子組件挖出了一個槽,可以用來填充內容。- 父組件中調用子組件時,子組件標簽之間的內容元素就是要放置的內容,它會把
slot
標簽替換掉。
最簡單的理解:我們的使用U
盤需要將U
盤插入USB
口中,此時USB
口就是插槽,U
盤就是插口。在Vue
中,<slot></slot>
就是電腦插槽,父組件的內容就可以理解為U
盤插口。
2.插槽默認內容
我們通常將插槽比作一個占位符,有內容進來時,自動把slot
給替換掉。但是,如果沒有內容進來時,那么應該渲染什么呢?
在很多場景下都會有這種需求,比如UI
組件庫中的彈窗,如果我們沒有傳入彈窗的頭部或者底部,那么彈窗便會有默認的樣式效果,這里就用到了slot
的默認內容功能。
修改一下 child.vue 代碼:
<template> <div class="child-box"> <p>我是子組件</p> <!-- 插槽 --> <slot> <p>我是默認內容</p> </slot> </div> </template>
當我們的App.vue
沒有向child
組件傳入內容時,會是什么效果呢?
App.vue 代碼如下:
<template> <img alt="Vue logo" src="./assets/logo.png" /> <child></child> </template>
輸出結果:
可以看到子組件同樣渲染了內容,而且就是slot
標簽內的內容。那么我們我們往child
組件傳入一點內容會是什么效果呢?
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
父組件傳入的內容了。
總結:
從上面例子不難看出,slot 標簽內的內容就是默認內容,也就是當父組件沒有傳遞給子組件內容時,子組件就會默認渲染 slot 內部的內容,但是 slot 標簽是不會渲染出來的。
3.具名插槽
很多時候我們子組件中都不止只有一個slot
,比如彈窗組件,我們可能允許調用者同時傳入header
、content
、footer
等等,這個時候如果子組件中只有一個slot
,那么這么多內容該如何區(qū)分,或者說該如何渲染呢?
3.1 基本使用
這個時候為了區(qū)分插槽與內容的對應關系,我們可以分別給slot
和內容都加上一個名字,插入插槽的時候大家按照名字區(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
添加內容了。
代碼如下:
<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
有了名字,那么我們在父組件中傳入內容時就要和名字關系對應起來,我們采用v-slot:header
指令的形式找到對應的插槽,需要注意的是該指令需要作用在template
元素上。從上圖可以看出,我們傳入的內容都渲染到了對應的插槽內,沒有命名的插槽渲染了我們傳入的未添加指令的內容。
3.2 簡寫
在Vue
中,很多指令都有簡寫形式,v-slot:name
指令也有簡寫形式,比如看我們下面的示例。
原寫法:
<template v-slot:footer> </template>
簡寫法:
<template #footer> </template>
接下來我們在借用官網(wǎng)的一張圖來清楚的了解具名插槽中的父子組件關系。
其中BaseLayout
為一個子組件,就和我們child
組件一樣。
3.3 默認插槽與具名插槽混用
當一個子組件中既有具名插槽,又有默認插槽時,該如何渲染呢?
前面我們說默認插槽會被隱式的命名為default
,所以我們傳入內容時可以將插槽名字改為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
來代表它,就好比人剛出生的時候沒有名字,但是他又一個默認屬性:“人”。
當然,既然大家都是默認的,在父組件中你也可以不用名字,這個時候內容會默認傳入到未命名插槽中去。
代碼如下:
<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)插槽名傳入內容的示例。
5.插槽作用域問題
我們仔細思考插槽的使用,會發(fā)現(xiàn)這有一點類似于父子組件傳遞,只不過插槽傳遞的是模板內容罷了。那么涉及到傳值,就會有一個作用域的問題,我們回顧一下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ù)。
總結:
所以我們這里總結為兩點
- 插槽內容可以訪問到父組件的數(shù)據(jù)作用域,就好比上述中的
message
是父組件的。 - 插槽內容無法訪問到子組件的數(shù)據(jù),就好比上述
App.vue
中的插槽內容拿不到子組件child
的數(shù)據(jù)。
6.作用域插槽
前一節(jié)我們說父組件中的插槽內容是無法訪問到子組件中的數(shù)據(jù)的,但是,萬一我們有需求就是需要在插槽內容中獲取子組件數(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
標簽上添加了一些自定義屬性,屬性值就是我們想要傳遞給父組件的一些內容。在父組件App.vue
中通過v-slot="slotProps"
等形式接收子組件傳毒過來的數(shù)據(jù),slotProps
的名字是可以任意取的,它是一個對象,包含了所有傳遞過來的數(shù)據(jù)。
需要注意的是,子組件傳遞過來的數(shù)據(jù)只能在子組件這個標簽內使用。
解構寫法:
我們都知道對象是可以解構的,所以我們在父組件中還可以直接使用解構的寫法來獲取數(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=""
形式了,而是直接再插槽內容上采用#header=""
形式,當時這是簡寫形式,你也可以寫為:v-slot:header=""
總結
插槽的作用非常廣泛,學好插槽對我們的項目開發(fā)有著非常大的幫助,當然,想要非常優(yōu)雅的使用插槽,還是需要費一些功夫的。這里可以推薦大家去看一看element
組件庫中的table
的使用,看看它是如何使用插槽的,如何優(yōu)雅的將表格組件中的數(shù)據(jù)共享給父組件的。
到此這篇關于Vue3中slot插槽使用方式的文章就介紹到這了,更多相關Vue3插槽使用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
關于在vue 中使用百度ueEditor編輯器的方法實例代碼
這篇文章主要介紹了在vue 中使用百度ueEditor編輯器的方法實例代碼 ,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-09-09vue預覽 pdf、word、xls、ppt、txt文件的實現(xiàn)方法
這篇文章主要介紹了vue預覽 pdf、word、xls、ppt、txt文件的實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04laravel5.3 vue 實現(xiàn)收藏夾功能實例詳解
這篇文章主要介紹了laravel5.3 vue 實現(xiàn)收藏夾功能,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2018-01-01Vue?2?如何添加?register-service-worker?實現(xiàn)緩存請求的問題
這篇文章主要介紹了Vue?2?如何添加?register-service-worker?以實現(xiàn)緩存請求的目的,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-11-11Vue.js中provide/inject實現(xiàn)響應式數(shù)據(jù)更新的方法示例
這篇文章主要介紹了Vue.js中provide/inject實現(xiàn)響應式數(shù)據(jù)更新,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-10-10