vue如何通過(guò)插槽組件之間數(shù)據(jù)傳遞
vue通過(guò)插槽組件之間數(shù)據(jù)傳遞
1.父向子傳值
//--->Father.vue
<template>
<div id="father">
<p>黃色為父組件---data的值為:{{ data }}</p>
<Son>
<template #usname>
<p>data的值為:{{data}}</p>//將父組件的data數(shù)據(jù)傳入子組件的<slot>插槽
</template>
</Son>
</div>
</template>
<script>
import Son from "./Son.vue";
export default {
data() {
return {
data: "Father",
};
},
components: {
Son,
},
};
</script>
<style scoped>
#father {
width: 400px;
height: 400px;
background-color: yellow;
}
</style>
//--->son.vue
<template>
<div id="son">
<p>藍(lán)色為子組件</p>
<slot name="usname"></slot>
</div>
</template>
<script>
export default {};
</script>
<style scoped>
#son {
width: 200px;
height: 200px;
background-color: skyblue;
}
</style>2.子向父?jìng)髦?/h3>
//--->Father.vue
<template>
<div id="father">
<p>黃色為父組件---data的值為:{{ data }}</p>
<button @click="upp">1</button>//點(diǎn)擊查看傳過(guò)來(lái)的值
<Son>
<template #usname="obj">//通過(guò)v-slot指令接收son.vue傳過(guò)來(lái)的值
<p>data的值為:{{ data }}</p>
<p>son_data的值為{{ obj.son }}</p>
<button @click="son_data = obj.son">1</button
>//通過(guò)點(diǎn)擊按鈕將傳過(guò)來(lái)的值保存在Father組件的son_data數(shù)據(jù)中
</template>
</Son>
</div>
</template>
<script>
import Son from "./Son.vue";
export default {
data() {
return {
data: "Father",
son_data: "",
};
},
components: {
Son,
},
methods: {
upp() {
console.log(this.son_data);
},
},
};
</script>
<style scoped>
#father {
width: 400px;
height: 400px;
background-color: yellow;
}
</style>
//--->Son.vue
<template>
<div id="son">
<p>藍(lán)色為子組件</p>
<slot name="usname" :son='son_data'></slot>//添加自定義屬性son將son_data數(shù)據(jù)傳入父組件
</div>
</template>
<script>
export default {
data(){
return{
son_data:'Son'
}
}
};
</script>
<style scoped>
#son {
width: 200px;
height: 200px;
background-color: skyblue;
}
</style>
//--->Father.vue
<template>
<div id="father">
<p>黃色為父組件---data的值為:{{ data }}</p>
<button @click="upp">1</button>//點(diǎn)擊查看傳過(guò)來(lái)的值
<Son>
<template #usname="obj">//通過(guò)v-slot指令接收son.vue傳過(guò)來(lái)的值
<p>data的值為:{{ data }}</p>
<p>son_data的值為{{ obj.son }}</p>
<button @click="son_data = obj.son">1</button
>//通過(guò)點(diǎn)擊按鈕將傳過(guò)來(lái)的值保存在Father組件的son_data數(shù)據(jù)中
</template>
</Son>
</div>
</template>
<script>
import Son from "./Son.vue";
export default {
data() {
return {
data: "Father",
son_data: "",
};
},
components: {
Son,
},
methods: {
upp() {
console.log(this.son_data);
},
},
};
</script>
<style scoped>
#father {
width: 400px;
height: 400px;
background-color: yellow;
}
</style>
//--->Son.vue
<template>
<div id="son">
<p>藍(lán)色為子組件</p>
<slot name="usname" :son='son_data'></slot>//添加自定義屬性son將son_data數(shù)據(jù)傳入父組件
</div>
</template>
<script>
export default {
data(){
return{
son_data:'Son'
}
}
};
</script>
<style scoped>
#son {
width: 200px;
height: 200px;
background-color: skyblue;
}
</style>vue跨組件動(dòng)態(tài)插槽傳遞
在看coderwhy老師后臺(tái)管理系統(tǒng)項(xiàng)目實(shí)戰(zhàn)視頻的時(shí)候發(fā)現(xiàn)組件封裝的思路與動(dòng)態(tài)插槽傳遞非常有意思,記錄一下!
需求及基本信息說(shuō)明

組件Goods調(diào)用組件page-content,組件page-content調(diào)用組件hy-table。
為了方便使用,組件page-content封裝公共插槽(如果將所有頁(yè)面的私有的插槽都一股腦放到組件page-content中封裝性會(huì)變差),需要在Goods中傳遞私有插槽內(nèi)容在hy-table中顯示。
這時(shí)候就產(chǎn)生了跨組件插槽傳遞的需求,而由于編譯作用域限制的原因,Goods組件中的#image不能直接被hy-table接收,而需要先由page-content接收goods中的數(shù)據(jù),再由page-content將數(shù)據(jù)傳遞到hy-table中。
而實(shí)際開(kāi)發(fā)中不可能在page-content中將插槽名稱寫(xiě)死,上面圖例page-content中只是簡(jiǎn)單拿#image進(jìn)行舉例,實(shí)際開(kāi)發(fā)中可以在組件page-content中動(dòng)態(tài)插入私有插槽,實(shí)現(xiàn)如下。
代碼
- Goods.vue
Goods中使用組件page-content并傳入配置文件contentTableConfig,并向page-content中名字為image的插槽提供內(nèi)容<el-image>
<template>
<div class="goods">
<page-content :contentTableConfig="contentTableConfig" pageName="goods">
<template #image="scope">
<el-image
style="width: 60px; height: 60px"
:src="scope.row.imgUrl"
:preview-src-list="[scope.row.imgUrl]"
>
</el-image>
</template>
<template #oldPrice="scope">{{ '¥' + scope.row.oldPrice }}</template>
</page-content>
</div>
</template>- contentTableConfig配置文件數(shù)據(jù)
其中slotName為status、createAt、updateAt、handler為公共插槽配置
export const contentTableConfig = {
title: '商品列表',
propList: [
{ prop: 'name', label: '商品名稱', minWidth: '80' },
{ prop: 'oldPrice', label: '原價(jià)格', minWidth: '80', slotName: 'oldPrice' },
{ prop: 'newPrice', label: '現(xiàn)價(jià)格', minWidth: '80' },
{ prop: 'imgUrl', label: '商品圖片', minWidth: '100', slotName: 'image' },
{ prop: 'status', label: '狀態(tài)', minWidth: '100', slotName: 'status' },
{
prop: 'createAt',
label: '創(chuàng)建時(shí)間',
minWidth: '250',
slotName: 'createAt'
},
{
prop: 'updateAt',
label: '更新時(shí)間',
minWidth: '250',
slotName: 'updateAt'
},
{ label: '操作', minWidth: '120', slotName: 'handler' }
],
showIndexColumn: true,
showSelectColumn: true
}- page-content.vue
定義一個(gè)函數(shù)otherPropSlots對(duì)配置信息進(jìn)行過(guò)濾,去掉公共的插槽名稱,剩下就是私有的插槽名稱了,返回一個(gè)包含私有插槽的數(shù)組,在template中對(duì)這個(gè)數(shù)組進(jìn)行遍歷,slot :name="私有插槽名"接收Goods中的內(nèi)容,“#私有插槽名”的template向子組件hy-table傳遞內(nèi)容
<template>
<div class="page-content">
<hy-table
v-bind="contentTableConfig"
>
<template #status="scope">
<el-button
plain
size="mini"
:type="scope.row.enable ? 'success' : 'danger'"
>
{{ scope.row.enable ? '啟用' : '禁用' }}
</el-button>
</template>
<template #createAt="scope">
<span>{{ $filters.formatTime(scope.row.createAt) }}</span>
</template>
<template #updateAt="scope">
<span>{{ $filters.formatTime(scope.row.updateAt) }}</span>
</template>
<template #handler>
<div class="handle-btns">
<el-button v-if="isUpdate" icon="el-icon-edit" size="mini" type="text"
>編輯</el-button
>
<el-button
v-if="isDelete"
icon="el-icon-delete"
size="mini"
type="text"
>刪除</el-button
>
</div>
</template>
<!-- 在page-content中動(dòng)態(tài)插入剩余的插槽 -->
<template
v-for="item in otherPropSlots"
:key="item.prop"
#[item.slotName]="scope"
>
<template v-if="item.slotName">
<slot :name="item.slotName" :row="scope.row"></slot>
</template>
</template>
</hy-table>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import HyTable from '@/base-ui/table'
export default defineComponent({
components: {
HyTable
},
props: {
contentTableConfig: {
type: Object,
require: true
},
pageName: {
type: String,
required: true
}
},
setup(props) {
// 獲取其他的動(dòng)態(tài)插槽名稱
const otherPropSlots = props.contentTableConfig?.propList.filter(
(item: any) => {
if (item.slotName === 'status') return false
if (item.slotName === 'createAt') return false
if (item.slotName === 'updateAt') return false
if (item.slotName === 'handler') return false
return true
}
)
return {
otherPropSlots
}
}
})
</script>想說(shuō)的話:
動(dòng)態(tài)傳遞插槽和封裝的思路絕了,需要花好多功夫和時(shí)間去消化~
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue系列之動(dòng)態(tài)路由詳解【原創(chuàng)】
下面小編就為大家?guī)?lái)一篇vue系列之動(dòng)態(tài)路由詳解【原創(chuàng)】。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就想給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09
vue通過(guò)路由實(shí)現(xiàn)頁(yè)面刷新的方法
本篇文章主要介紹了vue通過(guò)路由實(shí)現(xiàn)頁(yè)面刷新的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
詳解如何制作并發(fā)布一個(gè)vue的組件的npm包
這篇文章主要介紹了詳解如何制作并發(fā)布一個(gè)vue的組件的npm包,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11
Vue突然報(bào)錯(cuò)doesn‘t?work?properly?without?JavaScript?enabled
最近在做項(xiàng)目的時(shí)候遇到了些問(wèn)題,所以這篇文章主要給大家介紹了關(guān)于Vue突然報(bào)錯(cuò)doesn‘t?work?properly?without?JavaScript?enabled的解決方法,需要的朋友可以參考下2023-01-01
Vue的彈出框?qū)崿F(xiàn)圖片預(yù)覽和視頻預(yù)覽功能
本文介紹基于Vue3的媒體預(yù)覽組件,支持圖片與視頻預(yù)覽,具備縮放、旋轉(zhuǎn)、拖拽功能,采用ElementUI Dialog容器,通過(guò)計(jì)算屬性實(shí)現(xiàn)動(dòng)態(tài)樣式,優(yōu)化拖拽性能,自動(dòng)調(diào)整方向,便于集成使用2025-08-08

