作用域插槽(作用域插槽传值)(功能和作用的区别)
作用域插槽
一:假設第一個場景,需要你寫一個商品卡片組件,并通過循環去展示多個卡片,并且要求能響應每個卡片上的圖片或者其他內容的點擊事件而跳轉到商品詳情頁,你會怎么寫?
我會使用如下的處理方式,首先將商品卡片寫成一個組件Commodity.vue,而在CommodityList.vue中用一個v-for來處理商品卡片列表的展示。
<commodity v-for="(item,index) in commodities" @clickCommodity="onCommodityClick"></commodity>
Commodity組件通過$emit像父組件傳遞clickCommodity事件,并攜帶商品數據,父組件即可在onCommodityClick方法中得到數據,進行業務處理,這樣便完成了一個基本的由子到父的數據傳遞。
二:如果再往上抽象一下呢?比如我有多個運營欄目,像淘寶首頁有“有好貨”,“愛逛街”這樣兩個欄目,每個欄目下都需要有一個商品卡片列表,那么商品卡片列表CommodityList.vue就要抽成組件了。而這個包含多個運營欄目的vue組件我假設它叫ColumnList.vue,在其中通過v-for調用了CommodityList組件。
業務來了,我希望把點擊商品卡片的業務放在ColumnList.vue中處理。你們想象一下要怎么做?一種土辦法就是商品按鈕點擊時,Commodity組件 e m i t 通 知 C o m m o d i t y L i s t . v u e , 而 C o m m o d i t y L i s t 接 著 把 事 件 用 emit通知CommodityList.vue,而CommodityList接著把事件用 emit通知CommodityList.vue,而CommodityList接著把事件用emit往上拋,那么ColumnList.vue就能處理這個點擊事件了。這樣做完全沒有問題,但是顯得子組件很不純粹,跟業務都扯上關系了。
那么如何優雅地解決這個問題呢?這個時候,作用域插槽真正派上用場了。
通過作用域插槽將本應該由CommodityList處理的商品卡片點擊業務onCommodityClick提升到ColumnList處理。
而CommodityList組件內部應該是改造成這樣,slot接收來自父組件的商品卡片組件,這里面不涉及關于商品組件的業務,只關注其他業務和布局即可。最終就實現了組件和業務的剝離,這也是組件化的精髓所在吧。不知道有沒有幫到您呢?
1.可以在第一層監聽第三層組件的事件,并拿到第三層點擊對象的數據
2.數據來源于第一層
第一層 List.vue(ColumnList.vue)
<template>
<el-row :gutter="20">
<el-col :span="12" v-for="(column, index) in columnList" :key="index">
<el-card class="box-card card-column">
<div slot="header" class="clearfix">
<span>{
{
column.columnName}}</span>
</div>
<commodity-list :commodities="column.commodityList">
<template slot-scope="scope">
<!-- 這里只需要給Commodity組件傳入數據,響應Commodity組件的clickCommodity事件即可。
事件不必攜帶參數,完全符合父到子的數據流向,而不會發生子組件又給父組件反向發數據的情況 -->
<commodity :modityData="scope.row" @clickcommodity="onCommodityClick(scope.row)"></commodity>
</template>
</commodity-list>
</el-card>
</el-col>
</el-row>
</template>
<script>
import commodityList from './commodityList.vue'
import commodity from './commodity.vue'
export default {
components: {
commodityList,
commodity
},
data() {
return {
columnList: [
{
columnName: '愛好貨',
commodityList: [
{
id: 1, commodityName: 'iphone1', detail: 'iphone1 iphone1'
},
{
id: 2, commodityName: 'iphone2', detail: 'iphone2 iphone2'
},
{
id: 3, commodityName: 'iphone3', detail: 'iphone3 iphone3'
}
]
},
{
columnName: '愛逛街',
commodityList: [
{
id: 1, commodityName: 'iphone4', detail: 'iphone4 iphone4'
},
{
id: 2, commodityName: 'iphone5', detail: 'iphone5 iphone5'
},
{
id: 3, commodityName: 'iphone6', detail: 'iphone6 iphone6'
}
]
}
]
}
},
methods: {
onCommodityClick: function(i) {
console.log(i)
}
}
}
</script>
<style lang="less" scoped>
</style>
第二層 commodityList.vue
<template>
<el-row :gutter="20">
<el-col :span="8" v-for="(item, index) in commodities" :key="index">
<!-- <span>{
{
item}}</span> -->
<slot :row="item"></slot>
</el-col>
</el-row>
</template>
<script>
export default {
props: {
commodities: Array
},
data() {
return {
}
}
}
</script>
<style lang="less" scoped>
</style>
第三層 commodity.vue
<template>
<div>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>{
{
modityData.commodityName}}</span>
</div>
<div>
<span @click="$emit('clickcommodity')">{
{
modityData.detail}}</span>
</div>
</el-card>
</div>
</template>
<script>
export default {
props: {
modityData: Object
},
data() {
return {
}
}
}
</script>
<style lang="less" scoped>
.text {
font-size: 14px;
}
.item {
margin-bottom: 18px;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both
}
.box-card {
width: 480px;
}
</style>
vue卡片拖拽、自動排列交換位置、拖拽數據存取: https://www.cnblogs.com/xiaolucky/p/11699715.html.
vue封裝一個卡片組件https://blog.csdn.net/qq_44775782/article/details/104157324.
總結
以上是生活随笔為你收集整理的作用域插槽(作用域插槽传值)(功能和作用的区别)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Product Master data
- 下一篇: CORBA简介_吴帝聪简介