这里主要用到两个东西,一个是 render 函数,一个是递归,如果不熟悉 render 函数的道友请点这里。可能有道友会问为什么不用模板,因为······做不到啊😭,在 template 中只能有一个根元素,而 Vue 限制了不能对根元素使用 v-for;再者,通过在浏览器中查看代码可以知道,菜单就是 ul 加上 li,如果有了根元素会破坏标签结构(虽然不影响功能,但还是觉得不舒服😂)。然后,在需要使用的地方:
<template> <el-container> <el-aside> <Menu :data="menu" :collapse="isCollapsed"></Menu> </el-aside> <el-container> <el-header> <el-button type="text" icon="el-icon-d-arrow-left" @click="isCollapsed=!isCollapsed"></el-button> <h3>MenuName</h3> <span>MeFelixWang</span> </el-header> <el-main> <router-view></router-view> </el-main> </el-container> </el-container> </template> <script> import Menu from '@/components/Menu'; export default { name: 'App', data() { return { menu: [ { title: '导航一', id: 1, path: '', icon: 'el-icon-search', children: [ { title: '导航一杠一', id: 2, path: '', icon: '', children: [ {title: '导航一杠一杠一', id: 4, path: '/test', icon: '', children: []}, { title: '导航一杠一杠二', id: 5, path: '', icon: '', children: [ {title: '导航一杠一杠二杠一', id: 6, path: '/6', icon: '', children: []}, {title: '导航一杠一杠二杠二', id: 7, path: '/7', icon: '', children: []}, ] }, ] }, {title: '导航一杠二', id: 3, path: '/3', icon: '', children: []} ] }, {title: '导航二', id: 8, path: '/8', icon: 'el-icon-setting', children: []}, {title: '导航三', id: 9, path: '/9', icon: 'el-icon-document', children: []}, { title: '导航四', id: 10, path: '', icon: 'el-icon-date', children: [ {title: '导航四杠一', id: 11, path: '/11', icon: '', children: []}, { title: '导航四杠二', id: 12, path: '', icon: '', children: [ {title: '导航四杠二杠一', id: 14, path: '/14', icon: '', children: []} ] }, {title: '导航四杠三', id: 13, path: '/13', icon: '', children: []}, ] }, ], isCollapsed: false } }, methods: { handleOpen(key, keyPath) { console.log(key, keyPath); }, handleClose(key, keyPath) { console.log(key, keyPath); } }, components: { Menu } } </script> <style lang="stylus"> * margin 0 padding 0 html, body, .el-container, .el-aside height 100% .el-aside background-color rgb(84, 92, 100) .el-menu border-right solid 1px rgb(84, 92, 100) .el-header display flex justify-content space-between align-items center background-color aliceblue .el-button--text color: #606266; i font-weight bold </style>
效果如下:
需求四:这个 Select 选项是树形结构,一定得是树形结构
树形结构就树形结构吧,不就是样式嘛,改改应该就可以了。
<template> <div> <el-select v-model="tree" placeholder="请选择活动区域"> <el-option v-for="(item,index) in options" :key="index" :label="item.label" :value="item.id" :style="{paddingLeft:(item.level*10+20)+'px'}" :class="item.level?'is-sub':''"></el-option> </el-select> 选择的是:{{tree}} </div> </template> <script> export default { name: "Home", data() { return { tree: '', options: [], originData: [ { label: '这是根一', id: 1, children: [ {label: '这是茎一一', id: 2, children: []}, {label: '这是茎一二', id: 3, children: []}, { label: '这是茎一三', id: 4, children: [ {label: '这是叶一三一', id: 6, children: []}, {label: '这是叶一三二', id: 7, children: []}, ] }, {label: '这是茎一四', id: 5, children: []}, ] }, { label: '这是根二', id: 8, children: [], }, { label: '这是根三', id: 9, children: [ {label: '这是茎三一', id: 10, children: []}, { label: '这是茎三二', id: 11, children: [ {label: '这是叶三二一', id: 12, children: []} ] }, ], }, ] } }, created() { this.options = this.decomposeTree(this.originData, 0); }, methods: { //分解树形结构 decomposeTree(array, level) { let tmpArr = []; (function decompose(arr, lev) { for (let i = 0; i < arr.length; i++) { let tmpObj = {}; let item = arr[i]; item.level = lev; tmpObj = Object.assign({}, item); tmpArr.push(tmpObj); if (item.children) { decompose(item.children, lev + 1); //递归 } delete tmpObj.children; //删掉其 children,避免数据过大(不删也可以,也许后面有用呢) } })(array, level); return tmpArr; } } } </script> <style scoped lang="stylus"> .is-sub:before content '- ' </style>
因为 option 接收的是一个一维数组,所以通过递归展平树形结构,在展平的时候设置每项的层级,通过层级来设置缩进及前缀符号,效果如下: