vue目录树组件(树状结构列表)
一般数据类展示内容,大多采用树状结构展示内容。类似效果如下:
关注微信公众号,查看效果
左侧是导航分类,可以进行新建,对单项导航分享和删除。单击导航,在右侧查询出当前导航下所有目录结构,可以新建目录。新增类型分为三种,目录可以无限嵌套,当然也可以设置层级。
页面整体布局
页面分为左右两个部分。左侧列表,通过路由跳转显示右侧内容。左侧列表分为上下两块,顶部是添加按钮,下面是导航列表。
less样式。
import "../../theme/variables.less";
.main {
position: relative;
height: 100%;
overflow: hidden;
.content {
border: 1px solid #dcdcdc;
position: relative;
height: 100%;
background: #f1f2f7;
display: flex;
border-radius: @borderRadius;
.left {
width: 240px;
background: #fff;
border-right: 1px solid rgba(220, 220, 220, 1);
padding: 15px 10px;
display: flex;
flex-direction: column;
overflow: auto;
.header {
width: 100%;
margin-bottom: 20px;
display: flex;
justify-content: center;
align-items: center;
.btn {
width: 136px;
margin: 0 6px;
:global {
.icon {
margin-right: 14px;
}
.customIcon {
display: inline-block;
transform: rotate(45deg);
}
}
}
}
.treeLayout {
flex: 1;
.item {
width: 100%;
height: 32px;
line-height: 32px;
margin-bottom: 11px;
position: relative;
.link {
display: flex;
align-items: center;
font-size: 14px;
font-family: Microsoft YaHei;
font-weight: 400;
color: rgba(51, 51, 51, 1);
padding-left: 21px;
cursor: pointer;
.catalogIcon {
font-size: 12px;
}
.text {
display: inline-block;
flex: 1;
margin-left: 12px;
}
.opBtn {
width: 46px;
display: flex;
align-items: center;
justify-content: space-between;
}
.operateIcon {
display: none;
}
&:hover {
color: #00a4ff;
.opBtn {
color: rgba(51, 51, 51, 1);
}
.operateIcon {
display: block;
}
}
}
.iconBtns {
position: absolute;
top: 28px;
right: 24px;
width: 112px;
background: rgba(255, 255, 255, 1);
box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.13);
border-radius: 4px;
z-index: 10;
.icon {
width: 100%;
height: 40px;
border-radius: 2px;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-family: Microsoft YaHei;
font-weight: 400;
color: rgba(51, 51, 51, 1);
cursor: pointer;
.iconName {
margin-left: 18px;
}
&:hover {
background: #e7e8e9;
}
}
}
}
.itemActive {
.link {
color: #00a4ff;
.opBtn {
color: rgba(51, 51, 51, 1);
}
.operateIcon {
display: block;
}
}
}
}
}
.right {
flex: 1;
width: 100%;
overflow: hidden;
}
}
}
这里的导航列表,新增导航,和删除都是调用相关接口。
目录树组件
页面右侧就是树状结构列表,通过路由跳转携带catalogId参数,接口查询出列表数据,后端返回的数据就是有层级的树状结构。
我认为的写一个组件,单指这里的目录树组件,组件中只需要构造出页面布局,任何的交互逻辑都不涉及,只将相关事件抛出即可。这就需要先明确好数据结构,来写样式布局了。
数据结构,有id,name,父级id,子节点数组,类型catalogType:1是目录,2是场景,3是外链场景 ... 如下:
树状结构会涉及到递归,这里为了处理方便,组件中分为两层。组件目录结构如下:
index就是对外暴露的窗口,主要目录树的布局样式是在DomNode中。先明确一下布局,目录树中单个一行,需要一个展开收起的图标,当前行类型的图标,这里业务上分三种类型,就需要以此判断显示不同图标。每项最后还会有四个操作按钮。
这里把事件简化了,只分了两个事件,一个是展开收起,一个是一系列编辑操作,传个type参数作为区分。
tabNode(node: ITree) {
this.$emit("tabNode", node);
},
// 操作
doNode(node: ITree, type: string, index: number) {
this.$emit("doNode", node, type, index);
},
index文件中引用DomNode,相关的接收的参数和抛出去的事件,和DomNode一致。
// index布局
<div class="treeLayout">
<DomNode
v-for="(item, index) in trees"
:key="index"
:node="item"
@tabNode="tabNode"
@doNode="doNode"
:index="index"
></DomNode>
</div>
// 接收的参数
props: {
trees: {
type: Array as () => ITree[],
default: [],
},
activeId: {
type: String,
default: "",
},
},
页面右侧实现
引用catalogTree组件。
<catalog-tree
:trees="treeList"
@tabNode="tabNode"
@doNode="doNode"
></catalog-tree>
前文已经提过,目录数据是后端返回的,那么treeList就是后端返回值res.data。但操作tabNode和doNode这两个方法,需要将treeList数组转换成map对象。
因为需要自定义添加一些字段,这些字段只作为前端交互操作逻辑使用,所以后端返回值中不会携带。
需要给每一项数据添加isOpen字段,用来判断展开收起状态。level字段,用来实现上移下移操作。
先来构造这个catalogMap,定义个方法setCatalogMap,需要的参数有存放结果的treeMap,原数据treeList数组。
setCatalogMap,很简单的一个递归。
拿到map对象,就可以实现tabNode和doNode这两个方法。
// 切换状态
tabNode(node: ITree) {
if (node.isOpen) {
this.treeMap[node.catalogId].isOpen = false;
} else {
this.treeMap[node.catalogId].isOpen = true;
}
},
// 编辑等一系列操作,按照类型区分
doNode(node: ITree, type: string, index: number) {
switch (type) {
case "up":
// 上移
this.doUp(node, index);
break;
case "down":
// 下移
this.doDown(node, index);
break;
case "edit":
// 编辑
this.doEdit(node.catalogId);
break;
case "delete":
// 删除
this.doDelete(node);
break;
}
},
有认真看的话,会发现,并没有在哪里定义isOpen属性,怎么就在tabNode方法中使用了。
因为我还没有写。
拿到map对象,循环做个判断,用来保持isOpen状态。
Object.keys(treeMap).forEach((key) => {
const item = treeMap[key];
if (this.treeMap[key]) {
item.isOpen = this.treeMap[key].isOpen;
} else {
item.isOpen = true;
}
});
doNode中的四个方法,编辑和删除就是调个接口,主要是上移下移操作,前端实现数据的排序,最后将最新的数据返回给后端保存,doSaveSort方法调接口保存。
上代码,好好琢磨琢磨。
doUp(node: ICatalogModel, index: number) {
if (index === 0) {
return;
}
const parentId: string = node.catalogParent as string;
const parentItem: ICatalogModel = this.treeMap[parentId];
let dataList: ICatalogModel[] = [];
// 如果为空则是顶级
if (parentItem) {
if (parentItem.catalogTreeVoList) {
dataList = parentItem.catalogTreeVoList;
}
} else {
dataList = this.treeList;
}
const item = dataList[index];
dataList.splice(index, 1);
dataList.splice(index - 1, 0, item);
this.doSaveSort(dataList);
},
doDown(node: ICatalogModel, index: number) {
const parentId: string = node.catalogParent as string;
const parentItem: ICatalogModel = this.treeMap[parentId];
// 如果为空则是顶级
let dataList: ICatalogModel[] = [];
if (parentItem) {
if (parentItem.catalogTreeVoList) {
// 最后一个不能下移
if (parentItem.catalogTreeVoList.length === (index + 1)) {
return;
} else {
dataList = parentItem.catalogTreeVoList;
}
}
} else {
// 一级最后一个不能下移
if ( this.treeList.length === (index + 1)) {
return;
}
dataList = this.treeList;
}
const item = dataList[index];
dataList.splice(index, 1);
dataList.splice(index + 1, 0, item);
this.doSaveSort(dataList);
},
总结
树状结构列表,首先需要明确数据结构,必备的字段id,name,父级id,children数组,根据数据结构,使用递归构建布局。
vue目录树组件(树状结构列表)相关推荐
- ant design vue 中Upload组件如何自定义文件列表的样式
ant design vue 中Upload组件如何自定义文件列表的样式 问题 历程 UploadList 组件源码 h() 方法 实现 注 问题 技术:vue.ant design vue 在开发项 ...
- vue项目结合iview4UI组件实现树状结构及复杂动态表头列表 Tree-Table 及复杂header 省市区树状表格联动 数据优化后台一次性返回一万条数据页面卡死问题
一.首先看看需求最终效果图,该需求总共罗列以下几点 最左侧采用树状结构将地址省市区县街道展示出来,并且控制名称长度限制,多余的用省略号表示,鼠标悬浮上去名称展示出来 列表默认展示市一级数据,县及街道数 ...
- file类打印目录---树状结构,递归
package Test; import java.io.File; /** * file类打印目录---树状结构,递归 * @author Administrator * */ public cla ...
- Intellij IDEA如何将包的层级目录完全展现出来(树状结构)
compact middle packages紧凑的中间 这样包名树状结构就显示出来了,就不会隐藏了
- element表格多列排序_vue表格树状结构的实现
这绝对是我最后一次写树状结构,我非常的确定一定以及肯定! 上一篇文章总结了vue树状目录组件,忘记的可以点击传送门回顾一下: vue目录树组件 还是这个目录树,改版成 表格树状结构 . 我这里采用的U ...
- vue 循环 递归组件_全局组件实现递归树,避免循环引用
概述 目录分类展示会通常要用到树形结构.本例结合vue的父子组件,采用递归渲染,实现一个基于树的curd小demo 知识点 父子组件递归渲染 class 样式对象写法,CSS伪元素 ::before ...
- 我的前端工具集(四)树状结构后篇
我的前端工具集(四)树状结构后篇 liuyuhang原创,未经允许禁止转载 目录 我的前端工具集 上文连接 我的前端工具集(四)树状结构前偏 1.数据组织 在3.2.节有截图 2.树状结构代码 2 ...
- Jquery实现无限级树状结构并动态添加增删改等编辑功能
点击打开链接 源:http://www.56gee.com/Detail/2012/04/11/8AEB74E423/ <!DOCTYPE html PUBLIC "-//W3C//D ...
- ant vue 树形菜单横向显示_快速实现一个简单可复用可扩展的Vue树组件
来源 | https://wintc.top/article/13大概因为平时工作项目的原因,写了很多次树形组件,越写越觉得可以写得更简单并且更具有复用性.扩展性.树组件的应用场景很多,比如一篇文章的 ...
最新文章
- SQL Server中数据的修改是如何落盘的?
- 解决报错:error: function declaration isn’t a prototype [-Werror=strict-prototypes]
- jQuery 简单案例
- 乘基取整法是什么_数字逻辑电路-学习指南
- 实验7(2019.6.18)
- golang:map转json字符串
- user_agent
- 【FPGA——协议篇】:I2C总线协议详解+verilog源码
- CC2540蓝牙开发二 OSAL系统
- mysql中文本类型的长度限制_关于数据库:MySQL类型文本的最大长度
- iso硬盘安装 凤凰os_虚拟机安装凤凰系统(PhoenixOS)教程
- 卡通人“小糊涂”就要登场亮相
- flume中HDFS IO error
- 电子与通信工程专硕考分_分享我的苏州大学电子与通信工程专硕考研经历
- 【毕业设计】空气质量检测仪(环境检测盒子)- stm32 单片机 嵌入式 物联网
- 【机器人学、机器人控视觉与控制】四足机器人MATLAB仿真
- 甜椒刷机助手(安卓一键刷机助手) v3.5.1.1 电脑版
- 初识Git与GitHub和使用案例
- MFC程序逆向 – 消息篇(上)+(下)
- 设计模式普及之抽象工厂模式
热门文章
- 【NISP一级】考前必刷九套卷(七)
- 2021年安全员-B证考试资料及安全员-B证复审考试
- Precomputed Radiance Transfer for Real-Time Rendering in Dynamic, Low-Frequency Lighting Environment
- All About Testing
- 5611BH一位数码管及SMA420354L四位数码管引脚图
- 学习 Butterfly主题美化 这一篇就够了
- HDU 5536 Chip Factory (01字典树)
- SAP中重复制造生产计划编制——工序分解(分解数)
- 分离变量法过程(弦振动为例)
- educoder第1关:任务1:CTGU实验2-查询20