226 字
1 分钟
Vue组件递归
定义
组件递归即在组件的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' } }} 分享
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时
相关文章 智能推荐