mobile wallpaper 1
mobile wallpaper 2
mobile wallpaper 3
mobile wallpaper 4
226 字
1 分钟
Vue组件递归
2021-07-09

定义#

组件递归即在组件的tempalte内自己调用自己,需要设置组件的name属性

常用于不确定层级数量的独立组件,如级联选择器、树状结构等

简单实现#

简单的递归组件如下:

template部分

<div v-for="(item, index) in dataList">
<tree :dataList="item.children"></tree>
</div>

script部分

export default {
// 必须写 name !!!
name: 'tree',
prop: {
dataList: {
type: Array,
default: () => []
}
}
}

实例#

需求:结合 element-ui,封装一个基于 el-menu 的递归组件

实现效果:传入一个嵌套数组数据,依照数据的children数组属性实现多级数据渲染,且包含除第一级菜单以外均可能包含一个article数组,需要同时渲染,children内为子节点,只可展开不可点击,article 内为最终可点击的列表项。效果图如下: 实现效果图

代码如下:

外层组件TreeMenu(包裹递归组件)#

template部分

<el-menu v-if="list && list.length" :default-active="defaultActive" unique-opened :router="router">
<menu-item
:list="list"
:base-path="basePath"
:children-attr-name="childrenAttrName"
:key-id-attr-name="keyIdAttrName"
:title-attr-name="titleAttrName"
:articles-attr-name="articlesAttrName"
:article-key-id-attr-name="articleKeyIdAttrName"
:article-title-attr-name="articleTitleAttrName"
></menu-item>
</el-menu>

script部分

import MenuItem from './MenuItem'
export default {
name: 'TreeMenu',
components: {
MenuItem
},
props: {
// 是否开启路由
router: {
type: Boolean,
default: false
},
// 数据数组
list: {
type: Array,
default: () => []
},
// 默认打开
defaultActive: {
type: String
},
// 基础路径,允许为空
basePath: {
type: String
},
// 主节点子节点数组属性名
childrenAttrName: {
type: String,
default: 'children'
},
// 主节点id属性名
keyIdAttrName: {
type: String,
default: 'newsCategoryId'
},
// 主节点标题属性名
titleAttrName: {
type: String,
default: 'newsCategoryName'
},
// 文章数组属性名
articlesAttrName: {
type: String,
default: 'articles'
},
// 文章项id属性名
articleKeyIdAttrName: {
type: String,
default: 'newsId'
},
// 文章项标题属性名
articleTitleAttrName: {
type: String,
default: 'newsTitle'
}
},
// 由于外界可能是动态传入此参数,故写在watch内
watch: {
defaultActive(val) {
// 当前路由链接与传入连接一致时,不再跳转,防止跳转相同路径报错
if (this.$route.path !== val) {
this.$router.push(val)
}
}
}
}
递归组件MenuItem#

template部分

<div>
<!--遍历第一层类目-->
<template v-for="item of list">
<el-submenu :key="item[keyIdAttrName]" :index="`${basePath}/${item[keyIdAttrName]}`">
<span slot="title">{{ item[titleAttrName] }}</span>
<!--递归遍历第二层-->
<menu-item
:list="item[childrenAttrName]"
:base-path="basePath"
:children-attr-name="childrenAttrName"
:key-id-attr-name="keyIdAttrName"
:title-attr-name="titleAttrName"
:articles-attr-name="articlesAttrName"
:article-key-id-attr-name="articleKeyIdAttrName"
:article-title-attr-name="articleTitleAttrName"
></menu-item>
<!--遍历第一层类目文章-->
<el-menu-item v-for="article of item[articlesAttrName]" :key="article[articleKeyIdAttrName]"
:index="`${basePath}/${article[articleKeyIdAttrName]}`">{{ article[articleTitleAttrName] }}
</el-menu-item>
</el-submenu>
</template>
</div>

script部分

export default {
name: 'MenuItem',
props: {
// 数据数组
list: {
type: Array,
default: () => []
},
// 基础路径,允许为空
basePath: {
type: String,
},
// 主节点子节点数组属性名
childrenAttrName: {
type: String,
default: 'children'
},
// 主节点id属性名
keyIdAttrName: {
type: String,
default: 'newsCategoryId'
},
// 主节点标题属性名
titleAttrName: {
type: String,
default: 'newsCategoryName'
},
// 文章数组属性名
articlesAttrName: {
type: String,
default: 'articles'
},
// 文章项id属性名
articleKeyIdAttrName: {
type: String,
default: 'newsId'
},
// 文章项标题属性名
articleTitleAttrName: {
type: String,
default: 'newsTitle'
}
}
}
分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Vue组件递归
https://marrydream.top/posts/web前端/vue组件递归/
作者
茉铃
发布于
2021-07-09
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录