700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > element-ui导航菜单(el-menu)实现树形结构侧边栏

element-ui导航菜单(el-menu)实现树形结构侧边栏

时间:2019-06-02 15:44:06

相关推荐

element-ui导航菜单(el-menu)实现树形结构侧边栏

文章目录

前言1、先上效果图2、具体实现2.1 定义Menu组件2.2 定义Slider组件,及树结构数据处理 3、激活菜单和展开菜单3.1 激活菜单3.2 展开菜单3.3 动态实现。 4、总结

前言

提示:

一般侧边菜单数据都是静态、少量数据。如何实现动态可配置?

可以通过接口返回的树形结构数据动态更新菜单条目


1、先上效果图

树形结构数据(模拟数据,实际开发中通过后台接口获取即可)

[{"nodeid": "777718a5-18a8-4955-928a-64b683513590","parentid": "","nodename": "目录1","children": [{"nodeid": "b278006e-cb28-4459-8f1a-e42202a96ce8","parentid": "777718a5-18a8-4955-928a-64b683513590","nodename": "目录1-1"}]},{"nodeid": "c47d3f14-9b78-46fc-ad76-52e5d4df2ef7","parentid": "","nodename": "目录2","children": [{"nodeid": "7c913e5d-0ec0-4152-b183-b001d6d92ed8","parentid": "c47d3f14-9b78-46fc-ad76-52e5d4df2ef7","nodename": "目录2-1"},{"nodeid": "f1844722-ecaa-4e10-86f1-b64e3352d5ea","parentid": "c47d3f14-9b78-46fc-ad76-52e5d4df2ef7","nodename": "目录2-2"},{"nodeid": "ffff9811-ac84-41d9-b4d6-bcb98bf0196f","parentid": "c47d3f14-9b78-46fc-ad76-52e5d4df2ef7","nodename": "目录2-3"}]},{"nodeid": "f59286d3-1fdc-4b7d-8fa3-c5df26e86e32","parentid": "","nodename": "目录3","children": [{"nodeid": "127eb83b-2c58-4313-96ee-aa35c01b07e6","parentid": "f59286d3-1fdc-4b7d-8fa3-c5df26e86e32","nodename": "目录3-1","children": [{"nodeid": "4749d51d-db82-4302-8f99-3c51bd1bd093","parentid": "127eb83b-2c58-4313-96ee-aa35c01b07e6","nodename": "目录3-1-1"},{"nodeid": "f73a4b82-cc2a-4b5e-8015-c28478718fca","parentid": "127eb83b-2c58-4313-96ee-aa35c01b07e6","nodename": "目录3-1-2"},{"nodeid": "9d38b195-e5d8-43c5-8c75-71ef52a1e1ec","parentid": "127eb83b-2c58-4313-96ee-aa35c01b07e6","nodename": "目录3-1-3"}]}]},{"nodeid": "f4872c95-9e15-4d9a-81f8-4c04c7b275a8","parentid": "","nodename": "目录4","children": [{"nodeid": "4bbbb72c-848a-4046-97fe-40939a335299","parentid": "f4872c95-9e15-4d9a-81f8-4c04c7b275a8","nodename": "目录4-1"},{"nodeid": "ccb75eba-1355-457a-8c67-a53af258e024","parentid": "f4872c95-9e15-4d9a-81f8-4c04c7b275a8","nodename": "目录4-2"},{"nodeid": "bec8cc74-84e7-4909-8cdc-9650aabf75ad","parentid": "f4872c95-9e15-4d9a-81f8-4c04c7b275a8","nodename": "目录4-3"},{"nodeid": "b7c6e31b-ce62-40a7-83d0-0363d48ad0a5","parentid": "f4872c95-9e15-4d9a-81f8-4c04c7b275a8","nodename": "目录4-4"}]},{"nodeid": "5e54c8f3-502a-4bed-8542-1e7208d18dad","parentid": "","nodename": "目录5","children": [{"nodeid": "4264fae0-e7e9-4d85-826e-f195e178704a","parentid": "5e54c8f3-502a-4bed-8542-1e7208d18dad","nodename": "目录5-1"},{"nodeid": "01d8e744-8b29-42e1-8f59-829dcf773644","parentid": "5e54c8f3-502a-4bed-8542-1e7208d18dad","nodename": "目录5-2"}]}]

效果

2、具体实现

使用element-ui 导航菜单组件NavMenu ,递归实现。

2.1 定义Menu组件

思路 :

1、递归,如果数据元素存在子树(children),调用Menu组件自身,传递子树数据(item.children)。

2、 有子树用el-submenu,反之用 el-menu-item 。

<template><div><div v-for="(item, index) in menuData" :key="index"><!-- 思路: 有子元素使用el-submenu 没有子元素使用el-menu-item --><el-submenu :index="item.nodeid" v-if="item.children && item.children.length > 0"><template slot="title">{{item.nodename }}</template>//递归调用<Menu :menuData="item.children"></Menu></el-submenu><el-menu-item :index="item.nodeid" v-else>{{item.nodename }}</el-menu-item></div></div></template><script>export default {//递归 这个名称要保持驼峰转短横线链接规则name: "Menu",props: {menuData: {type: Array,default: () => {return [];}}},components: {},data() {return {};},created() {},mounted() {},methods: {}};</script><style lang='less' scoped></style>

2.2 定义Slider组件,及树结构数据处理

<template><div style="width:200px;height:100%"><el-menu:default-active="defaultActive":default-openeds="openeds"class="el-menu-vertical-demo"@open="handleOpen"@close="handleClose"><Menu :menuData="menuData"></Menu></el-menu></div></template><script>import Menu from "@/views/elementUi/pages/Menu";import {uuid } from "@/common/utils.js";export default {name: "elSlider",components: {Menu },data() {return {menuData: [],nodePathData: [] //节点路径数据};},created() {},computed: {//默认展开的子菜单openeds() {let openedList = [];let resList = this.nodePathData.filter(el => {return el.some(item => {return item.nodename === "目录3-1-2";});});resList = resList[0];if (resList) {resList.forEach(item => {openedList.unshift(item.nodeid);});}console.log(JSON.stringify(openedList));return openedList;},//默认激活的子菜单defaultActive() {return this.openeds[this.openeds.length - 1];}},mounted() {this.$axios.get("JsonFile/opitions.json").then(res => {this.menuData = res.data;console.time("x");let nodeData = this.getNodeMsg(this.menuData, "目录3-1-2", "", []);console.log('节点数据:',JSON.stringify(nodeData));this.nodePathData = this.getAllNodePath(this.menuData, nodeData);console.log(JSON.stringify(this.nodePathData));console.timeEnd("x");});},methods: {handleOpen(key, keyPath) {console.log(key, keyPath);},handleClose(key, keyPath) {console.log(key, keyPath);},/*** @author: DuHui* @description:通过节点名称 递归获取节点信息* @param {array} data 树结构数据* @param {string} nodename 结点名称* @param {string} nodeid 节点id* @param {array} result 查询结果,可能会查到多个节点 格式见return* @returns {array}* [* {* nodename, //节点名称 通过名称查找结果不唯一* nodeid, //节点id 通过id查找结果唯一* parentId, //父节点id* }* ...* ]*/getNodeMsg(data, nodename, nodeid, result) {data.forEach(item => {if (item.nodename === nodename || item.nodeid === nodeid) {let {nodename, nodeid, parentid } = item;result.push({nodename, nodeid, parentid });}if (item.children && item.children.length > 0) {this.getNodeMsg(item.children, nodename, nodeid, result);}});return result;},/*** @author: DuHui* @description: 获取节点路径:通过节点parentid找父节点,再通过父节点找祖父节点,以此类推* @param {array} data 树形结构数据* @param {object} node 当前节点对象* @param {array} result 含有当前节点的数组* @returns {array} 当前节点的全路径节点数组*/getNodeFullPath(data, node, result) {//查找当前节点的父节点,let parent = this.getNodeMsg(data, "", node.parentid, []);result.push(parent[0]);if (parent[0] && parent[0].parentid) {this.getNodeFullPath(data, parent[0], result);}return result;},/*** @author: DuHui* @description: 一个或多个节点得全路径* @param {array} data 原始树形结构数据* @param {array} nodeData 节点数据集含parentid* @returns {array}*/getAllNodePath(data, nodeData) {let result = [];nodeData.forEach(item => {//查找当前节点的全路径let path = this.getNodeFullPath(data, item, [item]);result.push(path);});return result;}}};</script><style lang='less' scoped></style>

详解:

1、定义Slider组件,引入上面定义Menu组件,并通过props传递树结构数据。

2、getNodeMsg(data, nodename, nodeid, result):通过nodename或nodeid,递归获取当前结点数据。如获取"目录3-1-2",结果:

[{“nodename”:“目录3-1-2”,“nodeid”:“f73a4b82-cc2a-4b5e-8015-c28478718fca”,“parentid”:“127eb83b-2c58-4313-96ee-aa35c01b07e6”}]

3、getNodeFullPath(data, node, result):获取当前节点到根节点的路径。含有每个节点基本数据。如下:

[[{“nodename”:“目录3-1-2”,“nodeid”:“f73a4b82-cc2a-4b5e-8015-c28478718fca”,“parentid”:“127eb83b-2c58-4313-96ee-aa35c01b07e6”},{“nodename”:“目录3-1”,“nodeid”:“127eb83b-2c58-4313-96ee-aa35c01b07e6”,“parentid”:“f59286d3-1fdc-4b7d-8fa3-c5df26e86e32”},{“nodename”:“目录3”,“nodeid”:“f59286d3-1fdc-4b7d-8fa3-c5df26e86e32”,“parentid”:""}]]

4、getAllNodePath(data, nodeData) 通过nodename查到节点数据可能存在重复情况,通过循环获取所有满足节点路径即可。

3、激活菜单和展开菜单

3.1 激活菜单

default-acivite: 激活当前菜单。设置后高亮并展开当前节点

效果

3.2 展开菜单

default-openeds :设置默认展开菜单。这里default-openeds

是一个key数组,就是在组件中设置的Index值(我们index绑定值为nodeid)。

没有顺序要求,但是节点不能中断,含有其父节点、祖父节点、一直到根节点

怎么理解? 比如要你要展开3-1-2,那么也要添加3-1 和 3 这两个节点,不能只设置3-1-2。

如下:

效果

3.3 动态实现。

3.1 、3.2 为了了解组件展开机制,使用了静态数据演示,方便理解其组件内部原理。那么如何动态实现?

到这里就很简单了 ,2.2中getNodeFullPath和getAllNodePath 这两个方法我们已经可以获取到节点路径,使用vue计算属性,做简单计算即可。

代码实现

computed: {//默认展开的子菜单openeds() {let openedList = [];let resList = this.nodePathData.filter(el => {return el.some(item => {return item.nodename === "目录3-1-2"; //要展开的节点});});resList = resList[0];if (resList) {resList.forEach(item => {openedList.unshift(item.nodeid);});}console.log(JSON.stringify(openedList));return openedList;},//默认激活的子菜单defaultActive() {return this.openeds[this.openeds.length - 1]; }},


4、总结

每天记录一点,从小小菜鸟变小菜鸟!!!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。