这是一个基于顺序表和树的数据结构,点击时异步获取数据,再点击即收起来,再点击时由于数据已经有了,直接展开,结合顺序遍历和递归遍历的树形组件。附上完整代码,如有疑问,可留言。
随便附上一个不规则树递归检索代码
/**
* 不规则树递归检索
*/
getTreeNodeById(id, trees) {
for (let tree of trees) {
if(tree.Id === id) {
return tree;
} else {
if(tree.Next.length > 0) {
return this.getTreeNodeById(id, tree.Next);
}
}
}
return {};
}
效果图:
LayoutAside.vue
<template>
<div class="page-container-aside">
<div class="page-container-aside-head">
<a class="edit-mail" href="/edit-mail" target="_blank">写邮件</a>
</div>
<div class="line"></div>
<div class="page-container-aside-body">
<div class="emails">
<tree
v-for="tree in trees"
:key="tree"
:treeList="tree"
>
</tree>
</div>
<div class="line"></div>
<ul class="functions">
<li
v-for="funItem in mailFunList"
:key="funItem.id"
>
<a
v-if="funItem.target === '_blank'"
:href="funItem.url"
:target="funItem.target"
>
{
{ funItem.text }}
</a>
<router-link
v-else
:to="funItem.url"
>
{
{ funItem.text }}
</router-link>
</li>
</ul>
</div>
</div>
</template>
<script>
/**
* 邮箱功能
*/
let mailFunList = [
{
id: 1,
text: '信息收集',
url: 'https://b5.office.cmbchina.com/InfoCol/Default.aspx',
target: '_blank'
},{
id: 2,
text: '个人模板',
url: '/setting/personal-template'
},{
id: 3,
text: '邮箱设置',
url: '/setting'
},{
id: 4,
text: '邮件备份',
url: 'http://99.3.14.178/MailBackupSvc',
target: '_blank'
},{
id: 5,
text: '邮箱管理',
url: 'https://office.cmbchina.com/mailrpt/Default.aspx',
target: '_blank'
},{
id: 6,
text: '问题反馈',
url: '/edit-mail',
target: '_blank'
}
]
import tree from '@/components/Tree.vue';
export default{
name: 'LayoutAside',
components: {
'tree': tree
},
data () {
return {
trees: [],
mailFunList: mailFunList
}
},
methods: {
/**
* 获取最初根结点的邮箱文件夹集合
*/
getOriginMailBoxList() {
this.$api.mailSetApi.getFolderById(
{id: '0'},
(data) => {
let folders = [];// 最初根结点的邮箱文件夹
for (let node of data) {
// 处理数据
let newNode = {
"id": node.id,
"name": node.name,
"hasChild": node.children,
"type": node.id,
"isOpen": false,
"next": []
};
folders.push(newNode);
}
this.trees = folders;
},
() => {}
);
},
},
created() {
/**
* 获取最初根结点的邮箱文件夹集合
*/
this.getOriginMailBoxList();
}
}
</script>
<style>
/* 侧边栏初始化 */
.page-container-aside{
position: absolute;
top: 0;
left: 0;
width: 170px;
height: 100%;
flex: 1;
}
.page-container-aside .page-container-aside-head{
position: relative;
text-align: center;
}
.page-container-aside .page-container-aside-body{
position: relative;
overflow-x: auto;
overflow-y: auto;
height: calc(100% - 55px);
}
/* / 侧边栏初始化 */
/* 分隔线 */
.page-container-aside .line{
clear: both;
border-top: solid #D8DEE5 1px;
}
/* / 分隔线 */
/* 写邮件的按钮 */
.page-container-aside .page-container-aside-head .edit-mail{
display: inline-block;
width: 100px;
height: 35px;
margin: 10px;
border: 1px solid #aaa;
border-radius: 5px;
color: #000;
line-height: 35px;
cursor: pointer;
font-size: 14px;
text-decoration: none;
}
/* / 写邮件的按钮 */
/* emails */
.page-container-aside .page-container-aside-body .emails{
/* width: 170px; */
/* overflow-x: auto; */
}
.page-container-aside .page-container-aside-body .emails .tree-ul li{
position: relative;
}
.page-container-aside .page-container-aside-body .emails .tree-ul li i {
display: inline-block;
position: absolute;
top: 4px;
width: 15px;
height: 15px;
margin: 0px 5px 0 10px;
border-radius: 4px;
border: solid 1px #bbb;
--gradient-start: #c1c1c1;
--gradient-start-text: #c1c1c1;
--gradient-end: #FAF8F9;
--gradient-end-text: '#FAF8F9';
background: linear-gradient(33deg, var(--gradient-start), var(--gradient-end));
cursor: pointer;
color: #646464;
font-size: 14px;
line-height: 14px;
font-style: normal;
text-align: center;
-moz-user-select:none;/*文字取消选中 - 火狐*/
-webkit-user-select:none;/*文字取消选中 - webkit浏览器*/
-ms-user-select:none;/*文字取消选中 - IE10*/
-khtml-user-select:none;/*文字取消选中 - 早期浏览器*/
user-select:none;
}
.page-container-aside .page-container-aside-body .emails .tree-ul li span {
display: inline-block;
position: relative;
top: 1px;
width: 120px;
padding: 2px 5px;
transition: all ease .1s;
-moz-user-select:none;/*文字取消选中 - 火狐*/
-webkit-user-select:none;/*文字取消选中 - webkit浏览器*/
-ms-user-select:none;/*文字取消选中 - IE10*/
-khtml-user-select:none;/*文字取消选中 - 早期浏览器*/
user-select:none;
color: #000;
font-size: 14px;
cursor: pointer;
text-decoration: none;
overflow: hidden;/* 单行文本显示省略号 */
text-overflow:ellipsis;/* 单行文本显示省略号 */
white-space: nowrap;/* 单行文本显示省略号 */
}
.page-container-aside .page-container-aside-body .emails .tree-ul .tree-li > span {
left: 35px;
}
.page-container-aside .page-container-aside-body .emails .tree-ul li .tree-ul .tree-li > span {
left: 35px;
}
.page-container-aside .page-container-aside-body .emails .tree-ul li span:hover {
color: #fff;
background-color: #AAD4FF;
}
.page-container-aside .page-container-aside-body .emails .tree-ul li .tree-ul .tree-li {
padding-left: 28px;
}
.page-container-aside .page-container-aside-body .emails .tree-ul li span.active {
color: #fff;
background-color: #ff5f5f;
}
/* / emails */
/* functions */
.page-container-aside .page-container-aside-body .functions li{
width: 100%;
text-align: center;
}
.page-container-aside .page-container-aside-body .functions li a{
display: block;
width: 100%;
height: 100%;
color: #000;
font-size: 14px;
line-height: 30px;
transition: all ease .3s;
text-decoration: none;
user-select: none;
}
.page-container-aside .page-container-aside-body .functions li a:hover{
color: #fff;
background-color: #AAD4FF;
}
/* / functions */
</style>
Tree.vue
<template>
<div class="tree">
<ul class="tree-ul">
<li class="tree-li">
<i
@click="toggle(mailTree)"
v-if="isFolder(mailTree)"
>
{
{ mailTree.isOpen ? '-' : '+' }}
</i>
<span
:class="setClass(mailTree)"
:title="mailTree.name"
@click.stop="routerGo(mailTree)"
>
{
{ mailTree.name }}
</span>
<tree
v-for="item in mailTree.next"
:treeList="item"
:key="item"
v-show="mailTree.isOpen"
>
</tree>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'tree',
props: ['treeList'],
data() {
return{
}
},
computed: {
/**
* 当前选中的文件夹ID
*/
curentFolderId: function() {
// console.log(this.$store.state.to);
let currentRoute = this.$store.state.to;
if (currentRoute.name !== 'mailList') {
if(currentRoute.name === 'home') {
return "1";
}
return '';
}
// console.log(currentRoute.params);
return (currentRoute.params !== undefined) && (currentRoute.params.fid !== undefined)
?
(
// console.log(this.$store.state.to.params.Id),
currentRoute.params.fid
)
:
(
// console.log(this.$store.state.to),
"1"
)
},
/**
* 监听树
*/
mailTree() {
return this.treeList;
}
},
methods: {
/**
* 判断是否为文件夹
*/
isFolder(mailTree) {
return mailTree.hasChild;
},
/**
* 点击设置文件夹激活样式
*/
setClass(mailTree) {
return {
active: this.curentFolderId == mailTree.id
}
},
/**
* 文件夹打开与关闭
*/
toggle(mailTree) {
// 判断是否已打开
if(mailTree.isOpen === true) {
mailTree.isOpen = !mailTree.isOpen;
} else {
// 判断是否有子集合
if(mailTree.hasChild) {
//判断子集合是否已经加载
if(mailTree.next.length > 0) {
mailTree.isOpen = !mailTree.isOpen;
} else {
try {
this.getMailBoxListById(mailTree);
mailTree.isOpen = !mailTree.isOpen;
} catch (error) {
alert("获取数据失败 =>", error);
}
}
}
}
},
/**
* 点击跳转文件夹路由
*/
routerGo(mailTree) {
this.$router.push ({
name: 'mailList',
params: {
fid: mailTree.id,
Name: mailTree.name,
folderType: mailTree.type,
r: new Date().getTime()
}
});
},
/**
* 根据Id获取下一层级的邮箱文件夹集合
*/
getMailBoxListById(mailTree) {
this.$api.mailSetApi.getFolderById(
{id: mailTree.id},
(data) => {
let next = [];// 下一层的邮箱文件夹
for (let node of data) {
// 处理数据
let newNode = {
"id": node.id,
"name": node.name,
"hasChild": node.children,
"type": mailTree.type,// 继承最初父级结点的type
"isOpen": false,
"next": []
};
next.push(newNode);
}
mailTree.next = next;
},
() => {}
);
},
/**
* 不规则树递归检索
*/
// getTreeNodeById(id, trees) {
// for (let tree of trees) {
// if(tree.Id === id) {
// return tree;
// } else {
// if(tree.Next.length > 0) {
// return this.getTreeNodeById(id, tree.Next);
// }
// }
// }
// return {};
// }
},
}
</script>