Vue3?通過作用域插槽實(shí)現(xiàn)樹形菜單嵌套組件
一、需求來源
工作中需要一種樹形菜單組件,經(jīng)過兩天的構(gòu)思最終通過作用域插槽實(shí)現(xiàn): 此組件將每個節(jié)點(diǎn)(插槽名為 node)暴露出來。
通過插槽的 attributes 向當(dāng)前插槽節(jié)點(diǎn)傳遞子項(xiàng) item(數(shù)據(jù)對象)和level(層深)參數(shù),在保持組件內(nèi)部極簡的同時支持在數(shù)據(jù)模型中擴(kuò)展性。基本達(dá)到比較好的封裝顆粒度,大家可以在此基礎(chǔ)上無限擴(kuò)展封裝具體的業(yè)務(wù)邏輯。
二、效果圖
let list = reactive(
[{
name:'1 一級菜單',
isExpand: true,//是否展開子項(xiàng)
enabled: false,//是否可以響應(yīng)事件
child:[
{ name:'1.1 二級菜單',
isExpand: true,
child:[
{ name:'1.1.1 三級菜單', isExpand: true, },
]
},
{ name:'1.2 二級菜單', isExpand: true, },
]
},
{
name:'1.1 一級菜單',
isExpand: true,
child:[
{ name:'1.1.1 二級菜單', isExpand: true, },
{ name:'1.1.2 二級菜單',
isExpand: false,
child:[
{ name:'1.1.2.1 三級菜單', isExpand: true, },
]},
]
},]
);

三、使用示例(VTreeNodeDemo.vue)
<template>
<VTreeNode
:list="list"
:level="level"
>
<template #node="slotProps">
<div class="tree-node">
{{prefix(slotProps.level)}}{{slotProps.item.name}}{{sufix(slotProps.item)}}
</div>
</template>
</VTreeNode>
</template>
<script setup>
import VTreeNode from '@/components/VTreeNode/VTreeNode.vue';
import { ref, reactive, watch, onMounted, } from 'vue';
let list = reactive(
[{
name:'1 一級菜單',
isExpand: true,//是否展開子項(xiàng)
enabled: false,//是否可以響應(yīng)事件
child:[
{ name:'1.1 二級菜單',
isExpand: true,
child:[
{ name:'1.1.1 三級菜單', isExpand: true, },
]
},
{ name:'1.2 二級菜單', isExpand: true, },
]
},
{
name:'1.1 一級菜單',
isExpand: true,
child:[
{ name:'1.1.1 二級菜單', isExpand: true, },
{ name:'1.1.2 二級菜單',
isExpand: false,
child:[
{ name:'1.1.2.1 三級菜單', isExpand: true, },
]},
]
},]
);
const level = ref(0);
const prefix = (count) => {
return '__'.repeat(count);
};
const sufix = (item) => {
if (!Reflect.has(item, 'child')) {
return '';
}
return ` (${item.child.length}子項(xiàng))`;
};
</script>
<style scoped lang='scss'>
.tree-node{
height: 45px;
display: flex;
justify-self: center;
align-items: center;
// background-color: green;
border-bottom: 1px solid #e4e4e4;
}
</style>
四、源碼(VTreeNode.vue):
<template>
<!-- <div> -->
<div v-for="(item,index) in list" :key="index">
<slot name="node" :item="item" :level="levelRef">
<div>{{ item.name }}</div>
</slot>
<div v-show="item.child && canExpand(item)" >
<VTreeNode :list="item.child" :level="levelRef">
<template #node="slotProps">
<slot name="node" :item="slotProps.item" :level="slotProps.level">
<div>{{ slotProps.item.name }}</div>
</slot>
</template>
</VTreeNode>
</div>
</div>
<!-- </div> -->
</template>
<script setup>
import { ref, reactive, watch, computed, onMounted, } from 'vue';
const props = defineProps({
list: {
type: Array,
default: () => [],
validator: (val) => {
return Array.isArray(val) && val.every(e => Reflect.has(e, 'name'));
}
},
level: {
type: Number,
default: 0,
}
});
const emit = defineEmits(['update:level', ])
const levelRef = computed({
set: (newVal) => {
if (props.level !== newVal) {
emit("update:level", newVal);
}
},
get: () => {
const tmp = props.level + 1;
return tmp;
},
});
const canExpand = (item) => {
return Reflect.has(item, 'isExpand') && item.isExpand;
};
// onMounted(() => {
// console.log(`levelRef:${levelRef.value}`);
// });
</script>
以上就是Vue3 通過作用域插槽實(shí)現(xiàn)樹形菜單/嵌套組件的詳細(xì)內(nèi)容,更多關(guān)于Vue3 樹形菜單嵌套組件的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue中頁面跳轉(zhuǎn)攔截器的實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于vue中頁面跳轉(zhuǎn)攔截器的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧。2017-08-08
Vue的route-view子頁面調(diào)用父頁面的函數(shù)詳解
這篇文章主要介紹了Vue的route-view子頁面調(diào)用父頁面的函數(shù)詳解,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07
Vue監(jiān)聽器簡單使用及注意事項(xiàng)說明
這篇文章主要介紹了Vue監(jiān)聽器簡單使用及注意事項(xiàng)說明,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08
關(guān)于webpack-dev-server配置代理解決前端開發(fā)中的跨域問題
這篇文章主要介紹了關(guān)于webpack-dev-server配置代理解決前端開發(fā)中的跨域問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08
玩轉(zhuǎn)vue的slot內(nèi)容分發(fā)
這篇文章主要介紹了玩轉(zhuǎn)vue的slot內(nèi)容分發(fā),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-09-09

