【vue3】实现el-tree组件,将不同层级的箭头修改成自定义图标的组件封装及调用

一、图例

 二、el-tree相关设置

1、实现只点击图标不点击文字展开下一级节点

<el-tree :expand-on-click-node="false"></el-tree>

2、实现为第一层文字加粗效果

<el-tree :props="{class: customNodeClass}"></el-tree>

<script lang='ts' setup>
import { onMounted, reactive } from 'vue';
const person = reactive({
  treeData:[
    {
      id: 1,
      label: '教材',
      isPenultimate: true,  // 在需要设置加粗的第一层加上这个属性
      children: [
        {
          id: 11,
          label: '一年级上册',
          children: [
            {
              id: 111,
              label: '我上学了',
            }
          ]
        }
      ]
    }
  ]
})

// 默认选中项样式
const customNodeClass = (data: any, node: Node) => {
  if (data.isPenultimate) {
    return 'is-penultimate'
  }
  return null
}
</script>

<style lang='scss' scoped>
:deep(.is-penultimate > .el-tree-node__content) {
  font-weight: bold;
}
</style>

3、将箭头修改成自定义图标

// 设置本身箭头为隐藏状态
:deep(.el-tree-node__expand-icon){
  width: 20px;
  padding: 0;
  margin: 5px 0;
  svg{
    display: none;
    width: 0;
  }
}
// 第一层
:deep(.el-tree-node){
  white-space: inherit;
  // 关闭状态
  .el-tree-node__expand-icon::before{
    background: url("../../../assets/img/new/jia_icon.png") no-repeat;
    content: '';
    display: block;
    width: 18px;
    height: 18px;
    background-size: 100% 100%;
  }
  // 展开状态
  .el-tree-node__expand-icon.expanded::before{
    background: url("../../../assets/img/new/jian_icon.png") no-repeat;
    content: '';
    display: block;
    width: 18px;
    height: 18px;
    background-size: 100% 100%;
  }
  // 没有子节点
  .el-tree-node__expand-icon.is-leaf::before {
    background: url("../../../assets/img/new/jian_icon.png") no-repeat;
    content: '';
    display: block;
    width: 18px;
    height: 18px;
    background-size: 100% 100%;
  }
  // 第二层
  & > .el-tree-node__children {
    // 关闭状态
    .el-tree-node__expand-icon::before{
      background: url("../../../assets/img/new/jia_yuan.png") no-repeat;
      content: '';
      display: block;
      width: 16px;
      height: 16px;
      background-size: 100% 100%;
    }
    // 展开状态
    .el-tree-node__expand-icon.expanded::before{
      background: url("../../../assets/img/new/jian_yuan.png") no-repeat;
      content: '';
      display: block;
      width: 16px;
      height: 16px;
      background-size: 100% 100%;
    }
    // 没有子节点
    .el-tree-node__expand-icon.is-leaf::before {
      background: url("../../../assets/img/new/jian_yuan.png") no-repeat;
      content: '';
      display: block;
      width: 16px;
      height: 16px;
      background-size: 100% 100%;
    }
  }
  // 第三层
  & > .el-tree-node > .el-tree-node__children {
    // 关闭状态
    .el-tree-node__expand-icon::before{
      background: url("../../../assets/img/new/jia_yuan.png") no-repeat;
      content: '';
      display: block;
      width: 16px;
      height: 16px;
      background-size: 100% 100%;
    }
    // 展开状态
    .el-tree-node__expand-icon.expanded::before{
      background: url("../../../assets/img/new/jian_yuan.png") no-repeat;
      content: '';
      display: block;
      width: 16px;
      height: 16px;
      background-size: 100% 100%;
    }
    // 没有子节点
    .el-tree-node__expand-icon.is-leaf::before {
      background: url("../../../assets/img/new/jian_yuan.png") no-repeat;
      content: '';
      display: block;
      width: 16px;
      height: 16px;
      background-size: 100% 100%;
    }
  }
}

4、文字选中状态,或鼠标经过的样式

// 文字选中样式
:deep(.el-tree-node:focus){
  >.el-tree-node__content{
    background-color: transparent;
    color: #2080F7;
  }
}
// 鼠标经过文字
:deep(.el-tree-node__content:hover){
   background-color: transparent;
   color: #2080F7;
}

5、设置节点默认选中项,通过高亮

<el-tree ref="myTree" :highlight-current="true" :current-node-key="person.treeCheckedData" node-key="Id"></el-tree>

<script lang='ts' setup>

import { reactive,onMounted,ref } from 'vue';
const person = reactive({
  treeData:[
    {
      id: 1,
      label: '教材',
      isPenultimate: true,
      children: [
        {
          id: 11,
          label: '一年级上册',
          children: [
            {
              id: 111,
              label: '我上学了',
            }
          ]
        }
      ]
    },
    ......
    ......
  ],
  treeCheckedData:0 // 默认选中项
})
const myTree=ref()

onMounted(()=>{
  load()
})
// 初始化
const load=()=>{
  person.treeData.forEach((tr:any,trIndex:number)=>{
     tr.children.forEach((chi:any)=>{
        // 符合条件就显示高亮
        if(chi.ObjId===person.prevIds.currId){
           nextTick(() => {
               myTree.value.setCurrentKey(chi.Id);
               // 或者 以下 2选1即可
               person.treeCheckedData=chi.Id
           });
        }
     })
  })
}

</script>

<style lang='scss' scoped>
// 设置自定义节点选中高亮样式
:deep(.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content){
    background-color: transparent;
    color: #2080F7;
 }
</style>

6、获取当前选中节点的父级节点信息

myTree.value.currentNode.parent

7、默认展开第一级节点

<el-tree node-key="id" :default-expanded-keys="person.treeExpandData"></el-tree>

<script lang='ts' setup>

import { reactive,onMounted } from 'vue';
const person = reactive({
  treeData:[
    {
      id: 1,
      label: '教材',
      isPenultimate: true,
      children: [
        {
          id: 11,
          label: '一年级上册',
          children: [
            {
              id: 111,
              label: '我上学了',
            }
          ]
        }
      ]
    },
    ......
    ......
  ],
  treeExpandData:[] // 默认展开数组
})

onMounted(()=>{
  load()
})
// 初始化
const load=()=>{
  person.treeExpandData.push(person.treeData[0].id)
}

</script>

三、完整代码

<template>
<div class="menu">
  <div class="menu_list">
    <el-tree :highlight-current="true" :current-node-key="person.treeCheckedData" node-key="Id" ref="myTree" :default-expanded-keys="person.treeExpandData" :expand-on-click-node="false" accordion :data="person.treeData" :props="{class: customNodeClass}" @node-click="onNodeClick" >
      <template #default="{ node,data }">
        <div class="tree_title">{{ node.label }}{{ data.id }}</div>
      </template>
    </el-tree>
  </div>
</div>
</template>
<script lang='ts' setup>
import { onMounted, reactive } from 'vue';
const person = reactive({
  treeData:[
    {
      id: 1,
      label: '教材',
      isPenultimate: true,
      children: [
        {
          id: 11,
          label: '一年级上册',
          children: [
            {
              id: 111,
              label: '我上学了',
            },
          ],
        },
      ],
    },
    {
      id: 2,
      label: '小升初',
      isPenultimate: true,
      children: [
        {
          id: 22,
          label: 'Level two 2-1',
          children: [
            {
              id: 222,
              label: 'Level three 2-1-1',
            },
          ],
        },
        {
          id: 23,
          label: 'Level two 2-2',
          children: [
            {
              id: 232,
              label: 'Level three 2-2-1',
            },
          ],
        },
      ],
    },
    {
      id: 3,
      label: '知识点',
      isPenultimate: true,
      children: [
        {
          id: 33,
          label: 'Level two 3-1',
          children: [
            {
              id: 333,
              label: 'Level three 3-1-1',
            }
          ]
        },
        {
          id: 34,
          label: 'Level two 3-2',
          children: [
            {
              id: 343,
              label: 'Level three 3-2-1',
            }
          ]
        }
      ]
    }
  ],
  treeExpandData:[],  // 默认展开项
  treeCheckedData:0 // 默认选中项
})

onMounted(()=>{
  load()
})
// 初始化
const load=()=>{
  person.treeExpandData.push(person.treeData[0].id)

  person.treeData.forEach((tr:any,trIndex:number)=>{
     tr.children.forEach((chi:any)=>{
        // 符合条件就显示高亮
        if(chi.ObjId===person.prevIds.currId){
           nextTick(() => {=
               myTree.value.setCurrentKey(chi.Id);
               // 或者 以下 2选1即可
               person.treeCheckedData=chi.Id
           });
        }
     })
  })
}

// 节点单击事件
const onNodeClick=()=>{

}
// 默认选中项样式
const customNodeClass = (data: any, node: Node) => {
  if (data.isPenultimate) {
    return 'is-penultimate'
  }
  return null
}
</script>
<style lang='scss' scoped>
 .menu {
  .menu_list{
    :deep(.el-tree-node__content){
      height: inherit;
      padding: 5px 0;
      align-items: center;
      &:hover{
        background-color: transparent;
        color: #2080F7;
      }
      .tree_title{
        margin-left: 5px;
        width: 90%;
        display: -webkit-box;
        -webkit-line-clamp: 1;
        overflow: hidden;
        -webkit-box-orient: vertical;
        text-overflow: ellipsis;
      }
      // 设置本身箭头为隐藏状态
      .el-tree-node__expand-icon{
        width: 20px;
        padding: 0;
        margin: 5px 0;
        svg{
          display: none;
          width: 0;
        }
      }
      // 禁止图标旋转
      .el-tree-node__expand-icon.expanded {
        -webkit-transform: rotate(0deg);
        transform: rotate(0deg);
      }
    }
    :deep(.is-penultimate > .el-tree-node__content) {
      font-weight: bold;
    }
    // 自定义节点高亮样式
    :deep(.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content){
      background-color: transparent;
      color: #2080F7;
    }
    // 文字选中状态
    :deep(.el-tree-node:focus){
      >.el-tree-node__content{
        background-color: transparent;
        color: #2080F7;
      }
    }
    // 第一层
    :deep(.el-tree-node){
      white-space: inherit;
      // 关闭状态
      .el-tree-node__expand-icon::before{
        background: url("../../../assets/img/new/jia_icon.png") no-repeat;
        content: '';
        display: block;
        width: 18px;
        height: 18px;
        background-size: 100% 100%;
      }
      // 展开状态
      .el-tree-node__expand-icon.expanded::before{
        background: url("../../../assets/img/new/jian_icon.png") no-repeat;
        content: '';
        display: block;
        width: 18px;
        height: 18px;
        background-size: 100% 100%;
      }
      // 没有子节点
      .el-tree-node__expand-icon.is-leaf::before {
        background: url("../../../assets/img/new/jian_icon.png") no-repeat;
        content: '';
        display: block;
        width: 18px;
        height: 18px;
        background-size: 100% 100%;
      }
      // 第二层
      & > .el-tree-node__children {
        // 关闭状态
        .el-tree-node__expand-icon::before{
          background: url("../../../assets/img/new/jia_yuan.png") no-repeat;
          content: '';
          display: block;
          width: 16px;
          height: 16px;
          background-size: 100% 100%;
        }
        // 展开状态
        .el-tree-node__expand-icon.expanded::before{
          background: url("../../../assets/img/new/jian_yuan.png") no-repeat;
          content: '';
          display: block;
          width: 16px;
          height: 16px;
          background-size: 100% 100%;
        }
        // 没有子节点
        .el-tree-node__expand-icon.is-leaf::before {
          background: url("../../../assets/img/new/jian_yuan.png") no-repeat;
          content: '';
          display: block;
          width: 16px;
          height: 16px;
          background-size: 100% 100%;
        }
      }
      // 第三层
      & > .el-tree-node > .el-tree-node__children {
        // 关闭状态
        .el-tree-node__expand-icon::before{
          background: url("../../../assets/img/new/jia_yuan.png") no-repeat;
          content: '';
          display: block;
          width: 16px;
          height: 16px;
          background-size: 100% 100%;
        }
        // 展开状态
        .el-tree-node__expand-icon.expanded::before{
          background: url("../../../assets/img/new/jian_yuan.png") no-repeat;
          content: '';
          display: block;
          width: 16px;
          height: 16px;
          background-size: 100% 100%;
        }
        // 没有子节点
        .el-tree-node__expand-icon.is-leaf::before {
          background: url("../../../assets/img/new/jian_yuan.png") no-repeat;
          content: '';
          display: block;
          width: 16px;
          height: 16px;
          background-size: 100% 100%;
        }
      }
    }
  }
}

</style>

       希望我的愚见能够帮助你哦~,若有不足之处,还望指出,你们有更好的解决方法,欢迎大家在评论区下方留言支持,大家一起相互学习参考呀~

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值