本文实例为大家分享了vue实现目录树结构的具体代码,供大家参考,具体内容如下
效果图
代码
组件部分 components/leftTree.vue
<template>
<div>
<ul class="all-list">
<li v-for="(item, i) in list" :key="item.key">
<!-- Antd的双击功能 这个看个人需求,不需要的话把'<div class="tree-item expend></div>'提取出来就可以了 -->
<a-dropdown :trigger="['contextmenu']">
<a-menu slot="overlay">
<a-menu-item key="1">
打开文件
</a-menu-item>
<a-menu-item key="2">
新建文件
</a-menu-item>
<a-menu-item key="3">
保存
</a-menu-item>
<a-menu-item key="4">
删除
</a-menu-item>
</a-menu>
<div class="tree-item expend">
<div
v-if="item.icon === 'file' || item.icon === 'openfile'"
class="icon-size"
:class="
openArr.includes(i) ? 'reduce-icon' : 'expend-icon'
"
@click="toggle(i)"
></div>
<i v-if="item.icon === 'file'"
><img src="../assets/file.png"
/></i>
<i v-if="item.icon === 'openfile'"
><img src="../assets/openfile.png"
/></i>
<i v-if="item.icon === 'vue'"
><img src="../assets/Vue.png"
/></i>
<i v-if="item.icon === 'js'"
><img src="../assets/js.png"
/></i>
<i v-if="item.icon === 'react'"
><img src="../assets/React.png"
/></i>
<i v-if="item.icon === 'sass'"
><img src="../assets/Sass.png"
/></i>
<i v-if="item.icon === 'vim'"
><img src="../assets/vimeo.png"
/></i>
<i v-if="item.icon === 'ts'"
><img src="../assets/ts.png"
/></i>
<i v-if="item.icon === 'php'"
><img src="../assets/php.png"
/></i>
<i v-if="item.icon === 'less'"
><img src="../assets/less.png"
/></i>
<i v-if="item.icon === 'java'"
><img src="../assets/java.png"
/></i>
<i v-if="item.icon === 'c++'"
><img src="../assets/c++.png"
/></i>
<i v-if="item.icon === 'markdown'"
><img src="../assets/markdown.png"
/></i>
<i v-if="item.icon === 'py'"
><img src="../assets/py.png"
/></i>
<i v-if="item.icon === 'go'"
><img src="../assets/go.png"
/></i>
<span class="content" @click="changeActive(item, i)">{{
item.title
}}</span>
</div>
</a-dropdown>
<!-- 递归 -->
<div
v-show="openArr.includes(i)"
v-if="item.children && item.children.length"
>
<leftTree class="item" :list="item.children"></leftTree>
</div>
</li>
</ul>
</div>
</template>
<script>
export default {
name: "leftTree",
data() {
return {
openArr: [],
checkboxIds: [],
};
},
props: {
list: {
type: Array,
},
},
methods: {
toggle(i) {
if (this.openArr.includes(i)) {
let index = this.openArr.indexOf(i);
this.openArr.splice(index, 1);
} else {
this.openArr.push(i);
}
},
changeActive(item, i) {
if (!item.children) {
if (item.icon === "file") {
this.toggle(i);
item.icon = "openfile";
} else if (item.icon === "openfile") {
this.toggle(i);
item.icon = "file";
} else {
alert("最后一个文件");
}
} else {
if (item.icon === "file") {
this.toggle(i);
item.icon = "openfile";
} else if (item.icon === "openfile") {
this.toggle(i);
item.icon = "file";
}
}
},
},
};
</script>
<style lang='less' scoped>
i {
line-height: 0;
img {
width: 16px;
height: 16px;
}
}
.item {
padding-left: 4px;
}
.bold {
font-weight: bold;
}
ul {
line-height: 1.5em;
list-style-type: none;
white-space: nowrap;
position: relative;
}
li {
list-style-type: none;
padding: 4px;
user-select: none;
}
.tree-item {
display: flex;
align-items: center;
}
.expend {
position: relative;
}
.expend::before {
content: "";
position: absolute;
width: 6px;
left: 9px;
top: 10px;
border-top: 1px dotted #c3c5c8;
}
.all-list::before {
content: "";
position: absolute;
width: 1px;
height: calc(100% - 40px);
left: 48px;
top: 20px;
border-left: 1px dotted #c3c5c8;
}
.item .expend::before {
content: "";
position: absolute;
width: 6px;
left: -11px;
top: 10px;
border-top: 1px dotted #c3c5c8;
}
.item .all-list::before {
content: "";
position: absolute;
width: 1px;
height: calc(100% - 12px);
left: 20px;
top: 0;
border-left: 1px dotted #c3c5c8;
}
.item ul {
padding-left: 2em;
}
.content {
padding-left: 4px;
transition: all 0.2s linear;
&:hover {
background: #c3c5c8;
}
}
.spacing {
display: inline-block;
width: 18.5px;
height: 1em;
}
.icon-size {
display: inline-block;
width: 16px;
height: 16px;
margin-right: 4px;
}
.expend-icon {
background: url("../assets/Plus.png") no-repeat center;
background-size: cover;
width: 9px;
height: 9px;
}
.reduce-icon {
background: url("../assets/minus.png") no-repeat center;
background-size: cover;
width: 9px;
height: 9px;
}
.ant-dropdown-menu {
width: 180px;
background: #353b44;
li {
color: #fff;
padding: 2px 10px;
&:hover {
background: rgb(13, 89, 175);
}
}
}
</style>
引用区域 views/home.vue
<template>
<div class="home">
<tree :list="line" />
</div>
</template>
<script>
import tree from "@/components/leftTree.vue";
export default {
name: "Home",
components: {
tree,
},
data() {
return {
line: [
{
title: "Project",
type: 1,
key: "1",
icon: "file",
children: [
{
title: "index.vim",
key: "1-1",
type: 3,
icon: "vim",
},
],
},
{
title: "Menu",
type: 1,
key: "2",
icon: "file",
},
{
title: "Components",
type: 1,
key: "3",
icon: "file",
children: [
{
title: "Index",
type: 2,
key: "3-1",
icon: "file",
children: [
{
title: "index.vue",
type: 3,
key: "3-1-1",
icon: "vue",
},
{
title: "index.react",
type: 3,
key: "3-1-2",
icon: "react",
},
{
title: "js",
type: 2,
key: "3-1-3",
icon: "file",
children: [
{
title: "index.js",
type: 3,
key: "3-1-1-1-1",
icon: "js",
},
],
},
{
title: "index.sass",
type: 3,
key: "3-1-4",
icon: "sass",
},
{
title: "index.less",
type: 3,
key: "3-1-5",
icon: "less",
},
],
},
{
title: "index.php",
type: 3,
key: "3-2",
icon: "php",
},
],
},
{
title: "node_modules",
type: 1,
key: "4",
icon: "file",
children: [
{
title: "index.java",
key: "4-1",
type: 3,
icon: "java",
},
{
title: "index.go",
key: "4-2",
type: 3,
icon: "go",
},
{
title: "index.py",
key: "4-3",
type: 3,
icon: "py",
},
{
title: "index.c",
key: "4-4",
type: 3,
icon: "c++",
},
{
title: "README.md",
key: "4-5",
type: 3,
icon: "markdown",
},
],
},
],
};
},
};
</script>
ps: 本人是前端小白,发帖只是为了做笔记,代码可能有很多的优化空间,另外也希望可以帮助到其他有需要的朋友
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。