赞
踩
ElementUI、ElementPlus树组件功能很不错,但是官方的树形组件没有显示线条,感觉稍微不够大气。于是网上查了一些资料,找了很多也感觉也不够完美,最后找到一个还不错的实现方案,并且再美化改进一下,分享给大家。
(1)示例代码
- <template>
- <div class="tree-container">
- <div style="padding: 20px;">
- <el-checkbox v-model="isSelectAll" @change="handleCheckedAllTreeNodeChange">全选/全不选</el-checkbox>
-
- <el-button size="mini" style="margin-left: 20px;" @click="handleGetCheckedNodesAndKeys(true)">获取已勾选节点</el-button>
- </div>
-
- <el-tree
- ref="treeRef"
- show-checkbox
- icon-class="el-icon-arrow-right"
- :node-key="'id'"
- :data="treeList"
- :props="defaultProps"
- :default-expand-all="true"
- :expand-on-click-node="false"
- :default-checked-keys="[5]"
- >
- <span slot-scope="{ data }">
- <template v-if="data.children">
- <div v-if="data.children.length > 0">
- <!-- <i class="el-icon-folder" :style="'font-size: 14px; padding: 0 5px 0 5px'"/> -->
- <i :style="'font-size: 13px; padding: 0 5px 0 5px'"><svg viewBox="64 64 896 896" data-icon="apartment" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M908 640H804V488c0-4.4-3.6-8-8-8H548v-96h108c8.8 0 16-7.2 16-16V80c0-8.8-7.2-16-16-16H368c-8.8 0-16 7.2-16 16v288c0 8.8 7.2 16 16 16h108v96H228c-4.4 0-8 3.6-8 8v152H116c-8.8 0-16 7.2-16 16v288c0 8.8 7.2 16 16 16h288c8.8 0 16-7.2 16-16V656c0-8.8-7.2-16-16-16H292v-88h440v88H620c-8.8 0-16 7.2-16 16v288c0 8.8 7.2 16 16 16h288c8.8 0 16-7.2 16-16V656c0-8.8-7.2-16-16-16zm-564 76v168H176V716h168zm84-408V140h168v168H428zm420 576H680V716h168v168z"></path></svg></i>
- <span>{{ data.id + ' - ' + data.label }}</span>
- </div>
-
- <div v-else>
- <i class="leaf-node-line"></i>
- <!-- <i class="el-icon-folder" :style="'padding: 0 5px 0 5px'"/> -->
- <i :style="'font-size: 13px; padding: 0 5px 0 5px'"><svg viewBox="64 64 896 896" data-icon="apartment" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M908 640H804V488c0-4.4-3.6-8-8-8H548v-96h108c8.8 0 16-7.2 16-16V80c0-8.8-7.2-16-16-16H368c-8.8 0-16 7.2-16 16v288c0 8.8 7.2 16 16 16h108v96H228c-4.4 0-8 3.6-8 8v152H116c-8.8 0-16 7.2-16 16v288c0 8.8 7.2 16 16 16h288c8.8 0 16-7.2 16-16V656c0-8.8-7.2-16-16-16H292v-88h440v88H620c-8.8 0-16 7.2-16 16v288c0 8.8 7.2 16 16 16h288c8.8 0 16-7.2 16-16V656c0-8.8-7.2-16-16-16zm-564 76v168H176V716h168zm84-408V140h168v168H428zm420 576H680V716h168v168z"></path></svg></i>
- <span>{{ data.id + ' - ' + data.label }}</span>
- </div>
- </template>
-
- <template v-else>
- <div style="margin-left: 0px;">
- <i class="leaf-node-line"></i>
- <!-- <i class="el-icon-document" :style="'padding: 0 5px 0 5px'"></i> -->
- <i :style="'font-size: 13px; padding: 0 5px 0 5px'"><svg viewBox="64 64 896 896" data-icon="deployment-unit" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M888.3 693.2c-42.5-24.6-94.3-18-129.2 12.8l-53-30.7V523.6c0-15.7-8.4-30.3-22-38.1l-136-78.3v-67.1c44.2-15 76-56.8 76-106.1 0-61.9-50.1-112-112-112s-112 50.1-112 112c0 49.3 31.8 91.1 76 106.1v67.1l-136 78.3c-13.6 7.8-22 22.4-22 38.1v151.6l-53 30.7c-34.9-30.8-86.8-37.4-129.2-12.8-53.5 31-71.7 99.4-41 152.9 30.8 53.5 98.9 71.9 152.2 41 42.5-24.6 62.7-73 53.6-118.8l48.7-28.3 140.6 81c6.8 3.9 14.4 5.9 22 5.9s15.2-2 22-5.9L674.5 740l48.7 28.3c-9.1 45.7 11.2 94.2 53.6 118.8 53.3 30.9 121.5 12.6 152.2-41 30.8-53.6 12.6-122-40.7-152.9zm-673 138.4a47.6 47.6 0 0 1-65.2-17.6c-13.2-22.9-5.4-52.3 17.5-65.5a47.6 47.6 0 0 1 65.2 17.6c13.2 22.9 5.4 52.3-17.5 65.5zM522 463.8zM464 234a48.01 48.01 0 0 1 96 0 48.01 48.01 0 0 1-96 0zm170 446.2l-122 70.3-122-70.3V539.8l122-70.3 122 70.3v140.4zm239.9 133.9c-13.2 22.9-42.4 30.8-65.2 17.6-22.8-13.2-30.7-42.6-17.5-65.5s42.4-30.8 65.2-17.6c22.9 13.2 30.7 42.5 17.5 65.5z"></path></svg></i>
- <span>{{ data.id + ' - ' + data.label }}</span>
- </div>
- </template>
- </span>
- </el-tree>
- </div>
- </template>
-
- <script>
- export default {
- data() {
- return {
- // 树列表
- treeList: [
- {
- id: 1,
- label: "香烟 WiFi 啤酒",
- children: [
- {
- id: 3,
- label: '香烟',
- children: [
- {
- id: 4,
- label: '煊赫门',
- },
- {
- id: 5,
- label: 'ESSE双爆珠',
- disabled: true,
- },
- ],
- },
- {
- id: 2,
- label: '后端开发技术',
- disabled: true,
- children: [
- {
- id: 6,
- label: 'Java编程技术',
- children: [],
- },
- {
- id: 7,
- label: '数据库',
- disabled: true,
- children: [
- {
- id: 8,
- label: '关系型数据库',
- children: [
- {
- id: 9,
- label: 'MySQL',
- },
- {
- id: 10,
- label: 'Oracle',
- disabled: true,
- },
- ],
- },
- {
- id: 11,
- label: '非关系型数据库',
- children: [
- {
- id: 12,
- label: 'Redis',
- },
- {
- id: 13,
- label: 'Elasticsearch',
- disabled: true,
- },
- ],
- }
- ],
- },
- ],
- },
- ],
- },
- ],
-
- // 对象关系映射
- defaultProps: {
- label: 'label',
- children: 'children',
- },
-
- // 是否全选所有节点标志
- isSelectAll: false,
- };
- },
- methods: {
- /**
- * 是否全选所有节点
- */
- handleCheckedAllTreeNodeChange() {
- if (this.isSelectAll) {
- // 深度遍历将子节点全选中
- for (let i = 0; i < this.treeList.length; i++) {
- this.$refs.treeRef.setChecked(this.treeList[i], true, true);
- }
- } else {
- // 全部不选中
- this.$refs.treeRef.setCheckedNodes([]);
- }
-
- const leafOnly = true;
- this.handleGetCheckedNodesAndKeys(leafOnly);
- },
-
- /**
- * 获取当前已被选中的节点集合
- */
- handleGetCheckedNodesAndKeys(leafOnly) {
- console.log('getCheckedNodes =>', this.$refs.treeRef.getCheckedNodes(leafOnly));
- console.log('getCheckedKeys =>', this.$refs.treeRef.getCheckedKeys(leafOnly));
- }
- },
- }
- </script>
-
- <style lang="less" scoped>
- // 设置树形组件节点的定位和左内边距
- .tree-container /deep/ .el-tree-node {
- position: relative;
- padding-left: 13px;
- }
-
- // 设置树形组件节点的 before 伪类的样式
- .tree-container /deep/ .el-tree-node:before {
- width: 1px;
- height: 100%;
- content: '';
- position: absolute;
- top: -38px;
- bottom: 0;
- left: 0;
- right: auto;
- border-width: 1px;
- border-left: 1px solid #b8b9bb;
- }
-
- // 设置树形组件节点的 after 伪类的样式
- .tree-container /deep/ .el-tree-node:after {
- width: 13px;
- height: 13px;
- content: '';
- position: absolute;
- left: 0;
- right: auto;
- top: 12px;
- bottom: auto;
- border-width: 1px;
- border-top: 1px solid #b8b9bb;
- }
-
- // 设置树形组件首节点的左边框不显示
- .tree-container /deep/ .el-tree > .el-tree-node:before {
- border-left: none;
- }
-
- // 设置树形组件首节点的顶部边框不显示
- .tree-container /deep/ .el-tree > .el-tree-node:after {
- border-top: none;
- }
-
- // 设置树形组件末节点的 before 伪类的高度
- .tree-container /deep/ .el-tree .el-tree-node:last-child:before {
- height: 50px;
- }
-
- // 设置树形组件节点字体大小、以及取消左内边距
- .tree-container /deep/ .el-tree .el-tree-node__content {
- color: #000;
- font-size: 14px;
- padding-left: 0 !important;
- }
-
- // 设置树形组件孩子节点左内边距
- .tree-container /deep/ .el-tree .el-tree-node__children {
- padding-left: 11.5px;
- }
-
- // 设置树形组件复选框左右外边距
- .tree-container /deep/ .el-tree .el-tree-node__content > label.el-checkbox {
- margin: 0 5px 0 5px !important;
- }
-
- // 设置树形组件展开图标定位、图层、内边距
- .tree-container /deep/ .el-tree .el-tree-node__expand-icon {
- position: relative;
- z-index: 99;
- }
-
- // 设置树形组件叶子节点的默认图标不显示
- .tree-container /deep/ .el-tree .el-tree-node__expand-icon.is-leaf {
- display: none;
- }
-
- // 设置树形组件叶子节点的横线
- .tree-container /deep/ .el-tree .leaf-node-line {
- width: 23px;
- height: 13px;
- content: '';
- position: absolute;
- left: 13px;
- right: auto;
- top: 12px;
- bottom: auto;
- border-width: 1px;
- border-top: 1px solid #b8b9bb;
- }
-
- // 设置树形组件有叶子节点的左外边距
- .tree-container /deep/ .el-tree .el-tree-node__content:has(.is-leaf){
- // color: aqua;
- margin-left: 24px !important;
- }
- </style>
(2)效果如下~
(1)示例代码
- <template>
- <div class="element-plus-tree">
- <el-tree
- :data="treeData"
- :props="defaultProps"
- :show-checkbox="false"
- :default-expand-all="true"
- :highlight-current="true"
- :expand-on-click-node="false"
- :indent="22"
- >
- <template #default="{ node, data }">
- <span v-if="!node.isLeaf" style="display: flex; align-items: center;">
- <el-icon v-if="node.expanded" style="margin: 0 6px 0 2px;" size="16"><FolderOpened /></el-icon>
- <el-icon v-else style="margin: 0 6px 0 2px;" size="16"><Folder /></el-icon>
- <small @click="handleNodeClick(node, data)">{{ node.label }}</small>
- </span>
-
- <span v-else style="display: flex; align-items: center;">
- <el-icon style="margin: 0 6px 0 2px;" size="16"><Document /></el-icon>
- <small @click="handleNodeClick(node, data)">{{ node.label }}</small>
- </span>
- </template>
- </el-tree>
- </div>
- </template>
-
- <script setup>
- import { onMounted, ref, getCurrentInstance } from 'vue'
-
- // 代理对象
- const { proxy } = getCurrentInstance()
-
- // 树型数据
- const treeData = ref(
- [
- {
- label: '香烟 WiFi 啤酒',
- expanded: true,
- children: [
- {
- label: '香烟',
- children: [
- {
- label: '煊赫门'
- },
- {
- label: 'ESSE双爆珠'
- }
- ],
- },
- {
- label: '后端开发技术',
- children: [
- {
- label: 'Java编程技术'
- },
- {
- label: 'Python编程技术'
- }
- ],
- },
- {
- label: '数据库',
- children: [
- {
- label: '关系型数据库',
- children: [
- {
- label: 'MySQL'
- },
- {
- label: 'Oracle'
- }
- ],
- },
- {
- label: '非关系型数据库',
- children: [
- {
- label: 'Redis'
- },
- {
- label: 'Elasticsearch'
- }
- ],
- }
- ],
- },
- {
- label: 'AI人工智能'
- },
- ],
- },
- {
- label: '火腿 iPad 泡面'
- },
- ]
- )
-
- // 树节点属性映射关系
- const defaultProps = {
- children: 'children',
- label: 'label',
- }
-
- /**
- * 树组件点击事件句柄方法
- */
- const handleNodeClick = (node, data) => {
- console.log(
- '%c 树组件点击事件句柄方法 %c handleNodeClick',
- 'padding: 1px; background-color: #35495e; color: #fff',
- 'padding: 1px; background-color: #5e7ce0; color: #fff',
- )
- console.log('%c ∟ %c node %c =>', 'text-indent: 10px', 'padding: 1px; background-color: #41b883; color: #fff', 'color: #000', node)
- console.log('%c ∟ %c data %c =>', 'text-indent: 10px', 'padding: 1px; background-color: #41b883; color: #fff', 'color: #000', data)
- }
-
- onMounted(() => {
- // ...
- })
- </script>
-
- <style lang="less" scoped>
- .element-plus-tree {
- padding: 100px;
-
- :deep(.el-tree) {
-
- .el-tree-node {
-
- /* ^ 所有节点 */
- i.el-tree-node__expand-icon {
- padding: 6px;
-
- &::before {
- font-family: element-ui-icons;
- font-style: normal;
- content: "\e6d9";
- color: #000000;
- border: 1px solid #606266;
- border-radius: 2px;
- }
-
- svg {
- display: none; // 隐藏所有节点的 svg 图标
- }
- }
- /* / 所有节点 */
-
- /* ^ 已展开的父节点 */
- i.el-tree-node__expand-icon.expanded {
- transform: rotate(0deg); // 取消旋转
- -webkit-transform: rotate(0deg); // 取消旋转
-
- &::before {
- font-family: element-ui-icons;
- font-style: normal;
- content: "\e6d8";
- color: #000000;
- border: 1px solid #606266;
- border-radius: 2px;
- }
- }
- /* / 已展开的父节点 */
-
- /* ^ 叶子节点 */
- i.el-tree-node__expand-icon.is-leaf {
-
- &::before {
- display: none;
- }
- }
- /* / 叶子节点 */
-
- /* ^ 复选框 */
- .el-checkbox {
- margin: 0 7px 0 2px;
-
- .el-checkbox__inner {
- width: 14px;
- height: 14px;
- border-radius: 2px;
- border: 1px solid #bbb;
- }
-
- .el-checkbox__input.is-checked .el-checkbox__inner,
- .el-checkbox__input.is-indeterminate .el-checkbox__inner {
- border: 1px solid #5e7ce0;
- }
- }
- /* / 复选框 */
-
- .el-tree-node__content {
- small {
- font-size: 13px;
- }
- }
- }
- }
- }
- </style>
(2)效果如下~
(1)示例代码
- <template>
- <div class="element-plus-tree">
-
- <el-tree
- :data="treeData"
- :props="defaultProps"
- :show-checkbox="true"
- :default-expand-all="true"
- :highlight-current="true"
- :expand-on-click-node="false"
- :indent="22"
- >
- <template #default="{ node, data }">
- <span v-if="!node.isLeaf" style="display: flex; align-items: center;">
- <el-icon v-if="node.expanded" style="margin: 0 6px 0 0px;" size="16"><FolderOpened /></el-icon>
- <el-icon v-else style="margin: 0 6px 0 0px;" size="16"><Folder /></el-icon>
- <small @click="handleNodeClick(node, data)">{{ node.label }}</small>
- </span>
-
- <span v-else style="display: flex; align-items: center;">
- <el-icon style="margin: 0 6px 0 0px;" size="16"><Document /></el-icon>
- <small @click="handleNodeClick(node, data)">{{ node.label }}</small>
- </span>
- </template>
- </el-tree>
- </div>
- </template>
-
- <script setup>
- import { onMounted, ref, getCurrentInstance } from 'vue'
-
- // 代理对象
- const { proxy } = getCurrentInstance()
-
- // 树型数据
- const treeData = ref(
- [
- {
- label: '香烟 WiFi 啤酒',
- expanded: true,
- children: [
- {
- label: '香烟',
- children: [
- {
- label: '煊赫门'
- },
- {
- label: 'ESSE双爆珠'
- }
- ],
- },
- {
- label: '后端开发技术',
- children: [
- {
- label: 'Java编程技术'
- },
- {
- label: 'Python编程技术'
- }
- ],
- },
- {
- label: '数据库',
- children: [
- {
- label: '关系型数据库',
- children: [
- {
- label: 'MySQL'
- },
- {
- label: 'Oracle'
- }
- ],
- },
- {
- label: '非关系型数据库',
- children: [
- {
- label: 'Redis'
- },
- {
- label: 'Elasticsearch'
- }
- ],
- }
- ],
- },
- {
- label: 'AI人工智能'
- },
- ],
- },
- {
- label: '火腿 iPad 泡面'
- },
- ]
- )
-
- // 树节点属性映射关系
- const defaultProps = {
- children: 'children',
- label: 'label',
- }
-
- /**
- * 树组件点击事件句柄方法
- */
- const handleNodeClick = (node, data) => {
- console.log(
- '%c 树组件点击事件句柄方法 %c handleNodeClick',
- 'padding: 1px; background-color: #35495e; color: #fff',
- 'padding: 1px; background-color: #5e7ce0; color: #fff',
- )
- console.log('%c ∟ %c node %c =>', 'text-indent: 10px', 'padding: 1px; background-color: #41b883; color: #fff', 'color: #000', node)
- console.log('%c ∟ %c data %c =>', 'text-indent: 10px', 'padding: 1px; background-color: #41b883; color: #fff', 'color: #000', data)
- }
-
- onMounted(() => {
- // ...
- })
- </script>
-
- <style lang="less" scoped>
- .element-plus-tree {
- padding: 100px;
-
- :deep(.el-tree) {
-
- /* ---- ---- ---- ---- ^(节点对齐)---- ---- ---- ---- */
- .el-tree-node {
-
- /* ^ 所有节点 */
- i.el-tree-node__expand-icon {
- padding: 6px;
-
- &::before {
- font-family: element-ui-icons;
- font-style: normal;
- content: "\e6d9";
- color: #000000;
- border: 1px solid #606266;
- border-radius: 2px;
- }
-
- svg {
- display: none; // 隐藏所有节点的 svg 图标
- }
- }
- /* / 所有节点 */
-
- /* ^ 已展开的父节点 */
- i.el-tree-node__expand-icon.expanded {
- transform: rotate(0deg); // 取消旋转
- -webkit-transform: rotate(0deg); // 取消旋转
-
- &::before {
- font-family: element-ui-icons;
- font-style: normal;
- content: "\e6d8";
- color: #000000;
- border: 1px solid #606266;
- border-radius: 2px;
- }
- }
- /* / 已展开的父节点 */
-
- /* ^ 叶子节点 */
- i.el-tree-node__expand-icon.is-leaf {
-
- &::before {
- display: none;
- }
- }
- /* / 叶子节点 */
-
- /* ^ 复选框 */
- .el-checkbox {
- margin: 0 7px 0 2px;
-
- .el-checkbox__inner {
- width: 14px;
- height: 14px;
- border-radius: 2px;
- border: 1px solid #bbb;
- }
-
- .el-checkbox__input.is-checked .el-checkbox__inner,
- .el-checkbox__input.is-indeterminate .el-checkbox__inner {
- border: 1px solid #5e7ce0;
- }
- }
- /* / 复选框 */
-
- .el-tree-node__content {
- small {
- font-size: 13px;
- }
- }
- }
- /* ---- ---- ---- ---- /(节点对齐)---- ---- ---- ---- */
-
- /* ---- ---- ---- ---- ^(文字高亮)---- ---- ---- ---- */
- .el-tree-node.is-current {
- .el-tree-node__content {
- small {
- color: #5e7ce0;
- }
- }
-
- .el-tree-node__children {
- small {
- color: unset;
- }
- }
- }
- /* ---- ---- ---- ---- /(文字高亮)---- ---- ---- ---- */
-
- /* ---- ---- ---- ---- ^(新增辅助线)---- ---- ---- ---- */
- /* ^ 树节点 */
- .el-tree-node {
- position: relative;
- width: auto;
- // width: max-content; // 显示文字宽度
- padding-left: 13px;
-
- &::before {
- width: 1px;
- height: 100%;
- content: '';
- position: absolute;
- top: -38px;
- bottom: 0;
- left: 0;
- right: auto;
- border-width: 1px;
- border-left: 1px solid #b8b9bb;
- }
-
- &::after {
- width: 13px;
- height: 13px;
- content: '';
- position: absolute;
- z-index: 0;
- left: 0;
- right: auto;
- top: 12px;
- bottom: auto;
- border-width: 1px;
- border-top: 1px solid #b8b9bb;
- }
-
- .el-tree-node__content {
- position: relative;
- z-index: 1;
- color: #000;
- padding-left: 0 !important;
-
- /* ^ 复选框 */
- .el-checkbox {
- margin: 0 10px 0 5.5px;
- }
- /* / 复选框 */
- }
-
- .el-tree-node__children {
- padding-left: 12px;
- }
-
- &:last-child::before {
- height: 50px;
- }
- }
- /* / 树节点 */
-
- /* ^ 第一层节点 */
- > .el-tree-node {
- padding-left: 0;
-
- &::before {
- border-left: none;
- }
-
- &::after {
- border-top: none;
- }
- }
- /* / 第一层节点 */
-
- /* ^ 叶子节点 */
- i.el-tree-node__expand-icon.is-leaf {
- display: none;
- }
- /* / 叶子节点 */
-
- /* ^ 设置子节点左外边距 */
- .el-tree-node__content:has(.is-leaf) {
- // color: #00ffff;
- margin-left: 25px !important;
- }
- /* / 设置子节点左外边距 */
- /* ---- ---- ---- ---- /(新增辅助线)---- ---- ---- ---- */
- }
- }
- </style>
(2)效果如下~
npm i vue-devui -D
(1)示例代码
- <template>
- <div class="vue-devui-tree">
-
- <div>
- <span>是否展开所有节点 : </span>
- <el-switch
- v-model="isExpandAllNodes"
- size="small"
- @change="handleIsExpandAllNodesChange"
- />
- </div>
-
- <DevTree ref="treeRef" :data="data">
- <template #icon="{ nodeData, toggleNode }">
- <span
- v-if="!nodeData.isLeaf"
- class="devui-tree__node-folder"
- @click="
- (event) => {
- event.stopPropagation();
- toggleNode(nodeData);
- }
- "
- >
- <!-- 未展开图标 -->
- <svg v-if="!nodeData.expanded" style="margin-right: 8px" width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg">
- <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
- <rect x="0.5" y="0.5" width="15" height="15" rx="2" stroke="#666666"></rect>
- <path fill="#666666" d="M8.75,4 L8.75,7.25 L12,7.25 L12,8.75 L8.749,8.75 L8.75,12 L7.25,12 L7.249,8.75 L4,8.75 L4,7.25 L7.25,7.25 L7.25,4 L8.75,4 Z"></path>
- </g>
- </svg>
-
- <!-- 已展开图标 -->
- <svg v-else style="margin-right: 8px" width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg">
- <g stroke-width="1" fill="none" fill-rule="evenodd">
- <rect x="0.5" y="0.5" width="15" height="15" rx="2" stroke="#666666"></rect>
- <rect x="4" y="7" width="8" height="2" fill="#666666"></rect>
- </g>
- </svg>
- </span>
-
- <span
- v-else
- class="devui-tree__node-leaf"
- >
- </span>
- </template>
-
- <template #content="{ nodeData }">
- <svg style="margin-right: 7px" viewBox="0 0 16 16" width="16" height="16">
- <path
- :d="`${
- nodeData.isLeaf
- ? 'M13,6 L9,6 L9,5 L9,2 L3,2 L3,14 L13,14 L13,6 Z M12.5857864,5 L10,2.41421356 L10,5 L12.5857864,5 Z M2,1 L10,1 L14,5 L14,15 L2,15 L2,1 Z'
- : nodeData.expanded
- ? 'M16,6 L14,14 L2,14 L0,6 L16,6 Z M14.7192236,7 L1.28077641,7 L2.78077641,13 L13.2192236,13 L14.7192236,7 Z M6,1 L8,3 L15,3 L15,5 L14,5 L14,4 L7.58578644,4 L5.58578644,2 L2,2 L2,5 L1,5 L1,1 L6,1 Z'
- : 'M14,6 L14,5 L7.58578644,5 L5.58578644,3 L2,3 L2,6 L14,6 Z M14,7 L2,7 L2,13 L14,13 L14,7 Z M1,2 L6,2 L8,4 L15,4 L15,14 L1,14 L1,2 Z'
- }`"
- stroke-width="1"
- fill="#8a8e99"
- ></path>
- </svg>
- <small>{{ nodeData.label }}</small>
- </template>
- </DevTree>
-
- </div>
- </template>
-
- <script setup>
- import { onMounted, ref, getCurrentInstance, toRaw } from 'vue'
- import { Tree as DevTree } from "vue-devui"
- import 'vue-devui/style.css'
-
- // 代理对象
- const currentInstance = getCurrentInstance()
-
- // 树型DOM引用
- const treeRef = ref()
-
- // 是否展开所有节点
- const isExpandAllNodes = ref(false)
-
- // 树型数据
- const data = ref(
- [
- {
- label: '香烟 WiFi 啤酒',
- expanded: true,
- children: [
- {
- label: '香烟',
- children: [
- {
- label: '煊赫门'
- },
- {
- label: 'ESSE双爆珠'
- }
- ],
- },
- {
- label: '后端开发技术',
- children: [
- {
- label: 'Java编程技术'
- },
- {
- label: 'Python编程技术'
- }
- ],
- },
- {
- label: '数据库',
- children: [
- {
- label: '关系型数据库',
- children: [
- {
- label: 'MySQL'
- },
- {
- label: 'Oracle'
- }
- ],
- },
- {
- label: '非关系型数据库',
- children: [
- {
- label: 'Redis'
- },
- {
- label: 'Elasticsearch'
- }
- ],
- }
- ],
- },
- {
- label: 'AI人工智能'
- },
- ],
- },
- {
- label: '火腿 iPad 泡面'
- },
- ]
- )
-
- /**
- * 是否展开所有节点句柄方法
- */
- const handleIsExpandAllNodesChange = (val) => {
- if (val) {
- handleExpandAllNodes()
- } else {
- handleCollapseAllNodes()
- }
- }
-
- /**
- * 将树节点全部展开句柄方法
- */
- const handleExpandAllNodes = () => {
- treeRef.value.treeFactory.expandAllNodes()
- }
-
- /**
- * 将树节点全部收起句柄方法
- */
- const handleCollapseAllNodes = () => {
- const treeFactory = treeRef.value.treeFactory
- const treeData = treeFactory.treeData._rawValue
- recursionCollapseNode(treeData)
- }
-
- /**
- * 递归收起节点句柄方法
- */
- const recursionCollapseNode = (treeData) => {
- for (let node of treeData) {
- if (node.expanded) {
- treeRef.value.treeFactory.collapseNode(node)
- }
-
- if (node.children && node.children.length > 0) {
- recursionCollapseNode(node.children)
- }
- }
- }
-
- onMounted(
- async () => {
- // Todo
- }
- )
- </script>
-
- <style lang="less" scoped>
- .vue-devui-tree {
- padding: 100px;
-
- :deep(.devui-tree) {
-
- .devui-tree__node-leaf {
- // display: none;
- position: relative;
- width: 16px;
- height: 16px;
- margin-right: 6px;
- // background-color: #ccc;
- // border: 1px solid #ccc;
- // border-radius: 2px;
- }
-
- .devui-tree__node-vline {
- margin-left: 4.5px;
- background-color: #cccccc !important;
- }
-
- .devui-tree__node-hline {
- margin-left: 4.5px;
- background-color: #cccccc !important;
- }
-
- .devui-tree__node {
-
- .devui-tree__node-content {
-
- &.active {
- // background-color: unset;
-
- small {
- color: #5e7ce0;
- }
- }
-
- &:hover {
- // background-color: unset;
- }
-
- small {
- font-size: 13px;
- transition: all ease 0.3s;
-
- &:hover {
- color: #5e7ce0;
- }
- }
- }
- }
- }
- }
- </style>
(2)效果如下~
(1)示例代码
- <template>
- <div class="vue-devui-tree">
-
- <DevTree ref="treeRef" :data="data" check>
- <template #icon="{ nodeData, toggleNode }">
- <span
- v-if="!nodeData.isLeaf"
- class="devui-tree__node-folder"
- @click="
- (event) => {
- event.stopPropagation();
- toggleNode(nodeData);
- }
- "
- >
- <!-- 未展开图标 -->
- <svg v-if="!nodeData.expanded" style="margin-right: 7px" width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg">
- <g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
- <rect x="0.5" y="0.5" width="15" height="15" rx="2" stroke="#666666"></rect>
- <path fill="#666666" d="M8.75,4 L8.75,7.25 L12,7.25 L12,8.75 L8.749,8.75 L8.75,12 L7.25,12 L7.249,8.75 L4,8.75 L4,7.25 L7.25,7.25 L7.25,4 L8.75,4 Z"></path>
- </g>
- </svg>
-
- <!-- 已展开图标 -->
- <svg v-else style="margin-right: 7px" width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg">
- <g stroke-width="1" fill="none" fill-rule="evenodd">
- <rect x="0.5" y="0.5" width="15" height="15" rx="2" stroke="#666666"></rect>
- <rect x="4" y="7" width="8" height="2" fill="#666666"></rect>
- </g>
- </svg>
- </span>
-
- <span
- v-else
- class="devui-tree__node-leaf"
- >
- </span>
- </template>
-
- <template #content="{ nodeData }">
- <svg style="margin: 0 7px" viewBox="0 0 16 16" width="16" height="16">
- <path
- :d="`${
- nodeData.isLeaf
- ? 'M13,6 L9,6 L9,5 L9,2 L3,2 L3,14 L13,14 L13,6 Z M12.5857864,5 L10,2.41421356 L10,5 L12.5857864,5 Z M2,1 L10,1 L14,5 L14,15 L2,15 L2,1 Z'
- : nodeData.expanded
- ? 'M16,6 L14,14 L2,14 L0,6 L16,6 Z M14.7192236,7 L1.28077641,7 L2.78077641,13 L13.2192236,13 L14.7192236,7 Z M6,1 L8,3 L15,3 L15,5 L14,5 L14,4 L7.58578644,4 L5.58578644,2 L2,2 L2,5 L1,5 L1,1 L6,1 Z'
- : 'M14,6 L14,5 L7.58578644,5 L5.58578644,3 L2,3 L2,6 L14,6 Z M14,7 L2,7 L2,13 L14,13 L14,7 Z M1,2 L6,2 L8,4 L15,4 L15,14 L1,14 L1,2 Z'
- }`"
- stroke-width="1"
- fill="#8a8e99"
- ></path>
- </svg>
- <small>{{ nodeData.label }}</small>
- </template>
- </DevTree>
-
- </div>
- </template>
-
- <script setup lang="ts">
- import { onMounted, ref, getCurrentInstance, toRaw, useCssModule, provide } from 'vue'
- import { Tree as DevTree } from "vue-devui"
- import 'vue-devui/style.css'
-
- // 代理对象
- const proxy = getCurrentInstance()
-
- // 树型DOM引用
- const treeRef = ref(null);
-
- // 树型数据
- const data = ref(
- [
- {
- label: '香烟 WiFi 啤酒',
- expanded: true,
- children: [
- {
- label: '香烟',
- children: [
- {
- label: '煊赫门'
- },
- {
- label: 'ESSE双爆珠'
- }
- ],
- },
- {
- label: '后端开发技术',
- children: [
- {
- label: 'Java编程技术'
- },
- {
- label: 'Python编程技术'
- }
- ],
- },
- {
- label: '数据库',
- children: [
- {
- label: '关系型数据库',
- children: [
- {
- label: 'MySQL'
- },
- {
- label: 'Oracle'
- }
- ],
- },
- {
- label: '非关系型数据库',
- children: [
- {
- label: 'Redis'
- },
- {
- label: 'Elasticsearch'
- }
- ],
- }
- ],
- },
- {
- label: 'AI人工智能'
- },
- ],
- },
- {
- label: '火腿 iPad 泡面'
- },
- ]
- )
-
- onMounted(() => {
- // 展开全部节点
- if (treeRef && treeRef.value) {
- const treeFactory: any = treeRef.value['treeFactory']
- treeFactory.expandAllNodes()
- }
- })
- </script>
-
- <style lang="less" scoped>
- .vue-devui-tree {
- padding: 100px;
-
- :deep(.devui-tree) {
-
- .devui-tree__node-leaf {
- // display: none;
- position: relative;
- width: 16px;
- height: 16px;
- margin-right: 6px;
- // background-color: #ccc;
- // border: 1px solid #ccc;
- // border-radius: 2px;
- }
-
- .devui-tree__node-vline {
- margin-left: 4.5px;
- background-color: #cccccc !important;
- }
-
- .devui-tree__node-hline {
- margin-left: 4.5px;
- background-color: #cccccc !important;
- }
-
- .devui-tree__node {
-
- .devui-tree__node-content {
-
- &.active {
- // background-color: unset;
-
- small {
- color: #5e7ce0;
- }
- }
-
- // &:hover {
- // background-color: unset;
- // }
-
- small {
- font-size: 13px;
- transition: all ease 0.3s;
-
- &:hover {
- color: #5e7ce0;
- }
- }
- }
- }
- }
- }
- </style>
(2)效果如下~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。