解決父子組件通信的三種Vue插槽
前言
插槽可以說是 Vue 中非常重要的一部分吧,在我學(xué)習(xí)和練習(xí)的過程中,當(dāng)組件搭配著插槽一起使用的時(shí)候,會(huì)發(fā)揮的更好一些。更多時(shí)候也會(huì)更加方便。
今天介紹Vue中三種插槽吧:默認(rèn)插槽、具名插槽、作用域插槽。
環(huán)境準(zhǔn)備
先搭個(gè)初始環(huán)境給大家看看哈。一步一步講完這個(gè)插槽。
就是寫了一個(gè)類別組件,分別渲染這三種數(shù)據(jù)。
Category組件
<template> <div class="category"> <h1>{{title}}</h1> <ul> <li v-for="(item,index) in listData" :key="index">{{item}}</li> </ul> </div> </template> <script> export default { props: { listData:Array, title: String } } </script> <style scoped> .category{ width: 200px; height: 300px; background-color:pink; } </style>
App組件
<template> <div id="app"> <Category :listData="games" :title="'Games'" /> <Category :listData="movies" :title="'Movies'" /> <Category :listData="foods" :title="'Foods'" /> </div> </template> <script> import Category from './components/Category.vue' export default { name: 'App', components: { Category }, data () { return { games:['穿越火線','qq飛車','洛克王國'], movies:['你好,李煥英','青春派','匆匆那年'], foods:['邵陽米粉','長沙茶顏','重慶火鍋'] } } } </script> <style> #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; display: flex; justify-content: space-between; } </style>
最開始就是如上圖一樣的需求,但是現(xiàn)在業(yè)務(wù)需求更改了,電影變成了只宣傳其中一個(gè),其他的不進(jìn)行宣傳,吃的也變成只宣傳一個(gè)拉。
如下圖:
我們怎么改合適呢?
是在Category組件中加if一個(gè)個(gè)進(jìn)行判斷嗎?還是有更好的方法勒???
一個(gè)個(gè)判斷是不行的,那樣子代碼會(huì)變得十分繁雜,不易閱讀,萬一以后又要更改業(yè)務(wù)需求,代碼都不好動(dòng)。
接下來就到默認(rèn)插槽的出現(xiàn)拉。
一、默認(rèn)插槽
我們在子組件中不用再用props 接收數(shù)據(jù),也不做渲染,而是定義一個(gè)插槽。
<template> <div class="category"> <!-- 定義插槽,插槽默認(rèn)內(nèi)容 --> <slot>如果當(dāng)父組件不傳值過來,即顯示此默認(rèn)</slot> </div> </template> <script> export default { props: { } } </script>
App組件也作出更改
<template> <div id="app"> <Category> <h1>Games</h1> <!-- <ul> <li v-for="(item, index) in games" :key="index">{{ item }}</li> </ul> --> <img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Farticle%2Fb352264fa7bfdb6d211f2e71e87cc2c48d85b805.jpg&refer=http%3A%2F%2Fi0.hdslb.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639931135&t=0b2c6c622c84a1e387196cce8f50455e"> </Category> <Category> <h1>Movies</h1> <img class="movies" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Finews.gtimg.com%2Fnewsapp_bt%2F0%2F13236694597%2F641.jpg&refer=http%3A%2F%2Finews.gtimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639931502&t=f89c2197bda9bb129d9404d3c4b30f2f"> <!-- <ul> --> <!-- <li v-for="(item, index) in movies" :key="index">{{ item }}</li> --> <!-- </ul> --> </Category> <Category> <h1>Foods</h1> <ul> <li v-for="(item, index) in foods" :key="index">{{ item }}</li> </ul> </Category> <!-- 當(dāng)我們什么都沒有寫的時(shí)候,看展示什么 --> <Category> </Category> </div> </template> <script> import Category from './components/Category.vue' export default { name: 'App', components: { Category }, data () { return { games:['穿越火線','qq飛車','洛克王國'], movies:['你好,李煥英','青春派','匆匆那年'], foods:['邵陽米粉','長沙茶顏','重慶火鍋'] } } } </script>
顯示效果:
解釋:
我們在子組件寫了一個(gè)<slot>如果當(dāng)父組件不傳值過來,即顯示此默認(rèn)</slot> 標(biāo)簽,此處就相當(dāng)于占了一個(gè)位置。
我們在父組件中,也不再像之前一樣<Category/>寫自閉和標(biāo)簽,而是寫了非自閉和標(biāo)簽<Category> 內(nèi)容 </Category>。這樣做,Vue就會(huì)默認(rèn)的將寫在組件標(biāo)簽中的內(nèi)容渲染完,然后再放回子組件中的 <slot></slot> 占好位置的地方去。
注意:CSS樣式寫在父組件或者子組件中都是可以的,因?yàn)樗卿秩就旰蟛欧呕刈咏M件中的。寫在子組件中,就是在放回子組件中時(shí)渲染。
寫完這里,客戶突然覺得你們這么厲害,不滿足啦,又開始給你們整幺蛾子。
接下來就又到具名插槽登場啦哈。
二、具名插槽
竟然我們能夠想到用一個(gè)插槽啦,那么為什么不能想著用兩個(gè)插槽來試一試?yán)眨?/p>
改造子組件
<template> <div class="category"> <!-- 必須加上名稱 在父組件中才能指定要放入那個(gè)插槽 這也是為什么叫做具名插槽的原因---> <slot name="slot1">如果當(dāng)父組件不傳值過來,即顯示此默認(rèn)</slot> <slot name="slot2"></slot> </div> </template> <script> export default { props: { } } </script>
父組件
<template> <div id="app"> <Category> <template slot="slot1"> <h1>Games</h1> <img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fi0.hdslb.com%2Fbfs%2Farticle%2Fb352264fa7bfdb6d211f2e71e87cc2c48d85b805.jpg&refer=http%3A%2F%2Fi0.hdslb.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639931135&t=0b2c6c622c84a1e387196cce8f50455e" /> </template> <template slot="slot2"> <button > qq登錄</button> <button > 微信登錄</button> </template> </Category> <Category> <template slot="slot1"> <h1>Movies</h1> <img class="movies" src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Finews.gtimg.com%2Fnewsapp_bt%2F0%2F13236694597%2F641.jpg&refer=http%3A%2F%2Finews.gtimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639931502&t=f89c2197bda9bb129d9404d3c4b30f2f" /> </template> <template slot="slot2"> <button > 點(diǎn)擊購票</button> </template> </Category> <Category> <template slot="slot1"> <h1>Foods</h1> <ul> <li v-for="(item, index) in foods" :key="index">{{ item }}</li> </ul> </template> </Category> <!-- 當(dāng)我們什么都沒有寫的時(shí)候,看展示什么 --> <Category> </Category> </div> </template> <script> import Category from './components/Category.vue' export default { name: 'App', components: { Category }, data () { return { games:['穿越火線','qq飛車','洛克王國'], movies:['你好,李煥英','青春派','匆匆那年'], foods:['邵陽米粉','長沙茶顏','重慶火鍋'] } } } </script>
效果展示
解釋:
我們可以在組件中放多個(gè)slot,但是多個(gè)的時(shí)候必須要給他們命名,另外父組件中也要進(jìn)行指定,這樣才不會(huì)放不進(jìn)去。
三、作用域插槽
作用域插槽和前面稍稍有點(diǎn)不同,之前都是數(shù)據(jù)在父組件中,而作用域插槽是數(shù)據(jù)在子組件中,反過來傳遞給父組件,讓父組件定義結(jié)構(gòu)進(jìn)行渲染。
改造的子組件
<template> <div class="category"> <slot name="slot1">如果當(dāng)父組件不傳值過來,即顯示此默認(rèn)</slot> <slot name="slot2" :foods="foods">如果當(dāng)父組件不傳值過來,即顯示此默認(rèn)</slot> </div> </template> <script> export default { data () { return{ foods:['邵陽米粉','長沙茶顏','重慶火鍋'] } } } </script>
父組件
<template> <div id="app"> <Category> <template slot="slot1"> <h1>Foods</h1> </template> <template slot="slot2" scope="listData"> <!--如果不知道的 咱們可以輸出看看這是什么· {{listData}} --> <ul> <li v-for="(item, index) in listData.foods" :key="index"> {{ item }} </li> </ul> </template> </Category> <Category> <template slot="slot1"> <h1>Foods</h1> </template> <template slot="slot2" scope="listData"> <ol> <li v-for="(item, index) in listData.foods" :key="index"> {{ item }} </li> </ol> </template> </Category> <Category> <template slot="slot1"> <h1>Foods</h1> </template> <template slot="slot2" scope="listData"> <h4 v-for="(item, index) in listData.foods" :key="index"> {{ item }} </h4> </template> </Category> <Category> <template slot="slot1" scope="listData"> {{listData}} </template> </Category> </div> </template> <script> import Category from './components/Category.vue' export default { name: 'App', components: { Category } } </script>
效果圖
這種我在學(xué)習(xí)及練習(xí)過程中,并沒有想到哪些使用場景,但是在官網(wǎng)上有案例,我想它必定是有存在的理由,只是我的見識(shí)太少,而未能利用到而已。
解釋:
子組件中通過:變量名="定義的數(shù)據(jù)" 向父組件傳值,父組件用 <template slot="slot2" scope="不用和子組件傳遞過來的名稱相同"> 接收,因?yàn)檫€要. 一層,才到
<template slot="slot2" scope="listData"> <!--如果不知道的 咱們可以輸出看看這是什么· {{listData}} --> <ul> <li v-for="(item, index) in listData.foods" :key="index"> {{ item }} </li> </ul> </template>
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
vue打印插件vue-print-nb的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue打印插件vue-print-nb的實(shí)現(xiàn),需要引入插件npm install vue-print-nb --save,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03淺析vue-router中params和query的區(qū)別
這篇文章主要介紹了vue-router中params和query的區(qū)別,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12vue在html標(biāo)簽{{}}中調(diào)用函數(shù)的方法總結(jié)及對比
這篇文章主要給大家介紹了關(guān)于vue在html標(biāo)簽{{}}中調(diào)用函數(shù)的方法總結(jié)及對比,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-03-03解決vue 界面在蘋果手機(jī)上滑動(dòng)點(diǎn)擊事件等卡頓問題
這篇文章主要介紹了vue 界面在蘋果手機(jī)上滑動(dòng)點(diǎn)擊事件等卡頓解決方案,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11vue實(shí)現(xiàn)圖片滑動(dòng)驗(yàn)證功能
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)圖片滑動(dòng)驗(yàn)證功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09