视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
vuejs实现递归树型菜单组件
2020-11-27 22:21:25 责编:小采
文档


前言

前段时间使用vue做了一套后台管理系统,其中使用最多就是递归组件,也因为自己对官方文档的不熟悉使得自己踩了不少坑,今天写出来和大家一起分享。

递归组件

组件在它的模板内可以递归地调用自己,只有当它有 name 选项时才可以。 在官网这句话就是关键定义组件是一定要有name属性。

模拟数据格式如下:

[
 {
 "id": "1",
 "menuName": "基础管理",
 "menuCode": "10",
 "children": [
 {
 "menuName": "用户管理",
 "menuCode": "11"
 },
 {
 "menuName": "角色管理",
 "menuCode": "12",
 "children": [
 {
 "menuName": "管理员",
 "menuCode": "121"
 },
 {
 "menuName": "CEO",
 "menuCode": "122"
 },
 {
 "menuName": "CFO",
 "menuCode": "123"
 },
 {
 "menuName": "COO",
 "menuCode": "124"
 },
 {
 "menuName": "普通人",
 "menuCode": "124"
 }
 ]
 },
 {
 "menuName": "权限管理",
 "menuCode": "13"
 }
 ]
 },
 {
 "id": "2",
 "menuName": "商品管理",
 "menuCode": ""
 },
 {
 "id": "3",
 "menuName": "订单管理",
 "menuCode": "30",
 "children": [
 {
 "menuName": "订单列表",
 "menuCode": "31"
 },
 {
 "menuName": "退货列表",
 "menuCode": "32",
 "children": []
 }
 ]
 },
 {
 "id": "4",
 "menuName": "商家管理",
 "menuCode": "",
 "children": []
 }
 ]

html我们思路按照ul里面套li,无限ul套li,标题用div元素包裹,

<template>
 <li>
 <span @click="toggle"> <!-- toggle:点击关闭展开 -->
 <i v-if="isFolder" class="icon" :class="[open ? 'folder-open' : 'folder']" @cilck="toggle"></i>
 <!-- <i v-if="isFolder" class="icon " :class="[open ? 'folder-open' : 'folder']"></i> -->
 <i v-if="!isFolder" class="icon folder-text"></i>
 {{model.menuName}}
 </span>
 <ul v-show="open" v-if="isFolder">
 <treeMenu v-for="item in model.children" :model="item"></treeMenu>
 </ul>
 </li>
</template>

官方文档里面写的递归组件强调了使用name属性

需要注意的是,由父组件传递过来的数据要先进行深拷贝哦

深拷贝:把props赋值到data里,赋值的同时深拷贝一下,data里 JSON.parse(JSON.stringify(这个值就行了)),data值自己命名

export default {
 name: 'treeMenu',
 //props: ['model'], //这样和下面效果一样
 props: {
 model: { type: Object },
 },
 components: {},
}

按照vue的思想,不操作Dom树,我们定义两个变量,一个显示隐藏子菜单(open),一个存不存子菜单修改图标(isFolder)。

 data() {
 return {
 open: false, //一个显示隐藏子菜单(open)
 //isFolder: true //这个不要写死,运用计算属性计算看存不存在
 }
 },

利用vue计算属性动态改变isFolder的值,修改图标,判断存在不子级和子级长度

 computed: {
 isFolder() { //利用vue计算属性动态改变isFolder的值,修改图标,判断存在不子级和子级长度
 // return this.model.children && this.model.children.length //和下面效果一样
 let isFolder = false
 if (this.model.children && this.model.children.length) {
 isFolder = true;
 } else {
 isFolder = false;
 }
 return isFolder
 }
 },

显示隐藏事件

 methods: {
 toggle() {
 if (this.isFolder) {
 this.open = !this.open
 }
 }
 },

写到这里我们已经做完一个树形菜单了

下载本文
显示全文
专题