vue目录树结构
冲浪选手CHARLIE 人气:0效果图
代码
组件部分 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: 本人是前端小白,发帖只是为了做笔记,代码可能有很多的优化空间,另外也希望可以帮助到其他有需要的朋友
加载全部内容