elementui中的tree组件相关操作集合

目录

1.刷新指定节点

2.自定义过滤方法

3.新增子节点

4.编辑节点名

5.拖拽节点

6.某节点高亮

7.总结

8. 组件整体的代码


1.刷新指定节点

node节点有一个loaded的属性,用来存储该节点是否展开过,

刷新指定节点的思路:无论该节点是否展开过,通通设置loaded=false,然后触发node节点的expand函数去展开节点

refreshNode(node){
  node.loaded = false
  node.expand()
},

2.自定义过滤方法

如果使用的不是懒加载,就可以直接使用官方给的方式去过滤,简单省事!

但是如果是使用的懒加载,就需要配合接口(跟获取节点是同一个接口,只是传递了过滤字段)处理了,就得自定义。

自定义过滤节点思路:带过滤参数从顶级节点开始展开,展开之后,根据子节点是否是叶子节点,再展开这些节点,这样一直展开下去,直到最里层

其实主要也是expand这个函数起的作用,真的很好用,界面上能看到一层一层的展开效果!

下面的代码仅供参考哦,html里很多data中的数据,懒得挨个复制了...重点看一下搜索区域和过滤函数(使用了递归)

<!-- 搜索区域 -->
<div class="menu-header">
  <el-input
      v-model="filterText"
      placeholder
      id="input"
      size="mini"
      suffix-icon="el-input__icon el-icon-search"
      @keyup.enter.native="filterMenu(-1)"
  ></el-input>
</div>
<!-- tree区域 -->
<el-scrollbar class="scrollbar-container" wrapStyle="margin-bottom:0">
      <el-tree
        ref="tree"
        lazy
        :load="loadNode"
        node-key="id"
        :props="defaultProps"
        :highlight-current="true"
        :expand-on-click-node="false"
        :current-node-key="currentNodekey"
        :default-expanded-keys="defaultExpandKeys"
        draggable
        :allow-drop="allowDrop"
        :allow-drag="allowDrag"
        @node-drag-start="handleDragStart"
        @node-drop="handleDrop"
        @node-click="handleNodeClick">
        <div class="custom-tree-node flex-space-between" slot-scope="{ node, data }" >
          <div class="tree-icon">
            <icon-svg class="file" icon-class="file"></icon-svg>
          </div>
          <div class="tree-label">
            <span v-show="editDirId !== data.id">
              {{node.label}}
              <template v-if="data.num">({{data.num}})</template>
            </span>
            <el-input
              :ref="data.id"
              v-show="editDirId === data.id"
              v-model.trim="data.title"
              size="mini"
              maxlength="15"
              @keyup.enter.native="$event.target.blur"
              @blur="labelBlur(node)"
            ></el-input>
          </div>
          <!-- 添加、编辑、删除按钮 -->
          <div class="tree-options">
            <!-- 带子节点的节点 有刷新功能 -->
            <i v-if="!node.isLeaf" class="btn blue el-icon-refresh" @click.stop="refreshNode(node)"></i>
            <!-- 添加节点 -->
            <i class="btn blue el-icon-plus" @click.stop="addNode(node)"></i>
            <!-- 我的目录(id=-1)不能修改 -->
            <i v-if="data.id != -1" class="btn el-icon-edit" @click.stop="showInput(data.id, data.title)"></i>
            <!-- 我的目录(id=-1)不能删除 :aaa=" data.id"-->
            <i v-if="data.id != -1"  class="btn red el-icon-delete" @click.stop="deleteDir(node, data.id)"></i>
          </div>
        </div>
      </el-tree>
    </el-scrollbar>
// 我的顶级目录是固定的,对应的值是-1
filterMenu(nodeId){
      // 过滤文本为空时,刷新顶级节点
      if(this.filterText.trim() == '') {
        let topNode = this.$refs.tree.getNode(-1)
        topNode.childNodes = []
        topNode.loaded = false
        topNode.expand()
        return
      }
      let node = this.$refs.tree.getNode(nodeId)
      // 重新展开该节点
      node.loaded = false
      node.expand(()=>{
        // 检查子元素是否有非叶子结点(注意:我们后台给的接口返回的isLeaf是字符串形式的true false)
        node.childNodes.forEach(item => {
          if(item.data.isLeaf == 'false'){
            // 递归处理含有子节点的节点
            this.filterMenu(item.data.id)
          }else{
            // 递归出口
          }
        });
      }) 
    },

看一下过滤之后的样子,带01的名字全部会展开

3.新增子节点

新增子节点,主要使用了tree提供的append函数,但是会有一些细节需要注意:比如说有的节点在还未加载的时候就新增子节点,会导致新增的节点没办法聚焦等问题

解决思路:先触发节点展开,展开之后再向其中追加子节点,子节点的名需要不重复

以下代码仅供参考,根据自己的情况做修改

addNode(node){
      node.expand(()=>{
        this.dirIdSuff = 0;
        let newDirName = this.getOnlyDirName('新建目录', node.childNodes)
        let order = node.childNodes.length > 0 ? node.childNodes[node.childNodes.length-1].data.ord + 1 : 0
        let newChild = { 
          title: newDirName, 
          isLeaf: "true",
          ord: order,
          num: 0
        } 
        // 调接口新增子节点
        insertDirectory({
          "parentId": node.data.id,
          "path": node.data.path,
          "title": newDirName,
          "ord": order
        })
        .then(res => {
          newChild.parentId = res.data.parentId
          newChild.id = res.data.id
          newChild.path = res.data.path
          this.$refs.tree.append(newChild, node)
          
          this.showInput(res.data.id, newChild.title)
        })
      })
},
// 节点显示编辑状态的输入框
showInput(id, title){
      this.oldDirName = title
      this.editDirId = id
      this.$nextTick(() => {
        this.$refs[id].focus()
      })
},
// 寻找一个合适的目录名
getOnlyDirName (title, arr) {
      let dirName = title + this.dirIdSuff
      isArray(arr)  ? '' : arr = []
      if(arr.find(val => val.data.title === dirName)){
        this.dirIdSuff++
        return this.getOnlyDirName(title, arr)
      }else{
        this.dirIdSuff = 0
        return dirName
      }
},

看一下效果

4.编辑节点名

使用懒加载的时候你会发现,节点的数据集合我们不会在data中管理,el-tree这个组件在懒加载的时候也不需要传入data,就像下面这样:

<!-- 基本用法 -->
<el-tree 
  :data="data" 
  :props="defaultProps" 
></el-tree>

<!-- 懒加载用法 -->
<el-tree
  :props="defaultProps"
  lazy
  :load="loadNode"
></el-tree>

 那我们在修改树节点的信息的时候就不能通过修改data去改变了...

解决思路:通过修改node中的data去改变树节点信息

node中存储的有该节点的基本信息(文章总结的地方有),还有渲节点时使用的data数据(也就是接口返回的某节点数据)

我的需求是点击了编辑按钮之后,显示节点的输入框供用户编辑,然后回车或者失焦,触发接口。来吧,上代码(html的部分前面自定义过滤方法的地方已经粘出来了,这里就不重复了)

// 点击了编辑按钮
showInput(id, title){
      // 保存修改前的目录名
      this.oldDirName = title
      // 修改当前处于编辑状态的节点,为了触发该节点显示输入框
      this.editDirId = id
      this.$nextTick(() => {
        // 输入框聚焦
        this.$refs[id].focus()
      })
},

// input失去焦点(编辑目录名)
labelBlur (node) {
      let data = node.data
      this.editDirId = ''
      // 名字相等的时候不用改
      if (data.title === this.oldDirName) return
      // 检查名字是否重复(isArray是我自己写的一个检查是否是数组的函数)
      let sameName = isArray(node.parent.childNodes) ? 
        node.parent.childNodes.some( childNode => childNode.data.title===data.title && childNode.data.id!==data.id )
        :
        false
      if(sameName) {
        data.title = this.oldDirName
        this.$message({
          type: 'error',
          message: '同目录不允许同名哦!'
        })
        return
      }

      // 目录名称校验,需要的自行添加这部分代码,我这里没有

      // 修改目录,调用接口
      updateDirectory({
        "id": data.id,
        "title": data.title
      })
      .then(res => {
        this.$message({ type: 'success', message: '修改成功!' })
      })
      .catch(() => {
        // 失败的话,将目录名复原
        data.title = this.oldDirName
      })
},

5.拖拽节点

el-tree组件也提供了节点的拖拽功能,但是当使用的时候还是会存在很多需要注意的地方的:

比如说:

拖拽三种情况,before,after,inner ,

我这里每个目录都包含了它的上级目录甚至还有一个path记录这个节点的在树中的层级关系,所以拖拽成功了的时候,一定得记得更新一下节点信息哦,要不然用户直接再拖拽这个节点,就会出问题了。

那要是拖拽失败了呢?我百度了很多,没看到别人对这种情况得处理,所以我自己处理了一下,将拖拽的那个节点位置复原

同样的html部分不重复了,去上面看一下就行,下面粘一下js部分(小括号标注了我的项目需求,方便各位看官能更快的修改成自己需要的代码)

// 允许放置的节点设置(我的需求是顶级目录只能允许用户inner节点进去)
allowDrop(draggingNode, dropNode, type) {
      if (dropNode.data.id == -1) {
        return type === 'inner';
      } else {
        return true;
      }
    },

// 允许拖拽的节点设置(我的需求是顶级节点不允许拖拽)
allowDrag(draggingNode) {
      return draggingNode.data.id != -1;
},

// 拖拽前: 保存被拖拽元素的下标(保存下来为了复原节点位置使用)
handleDragStart(draggingNode, event){
      draggingNode.parent.childNodes.forEach((childNode, nodeIndex) =>{
        if(childNode.key == draggingNode.key){
          this.beforeDragNodeIndex = nodeIndex
          return
        }
      })
},

// 拖拽完成(请求成功时:更新节点信息;请求失败时:节点位置复原)
handleDrop(draggingNode, dropNode, dropType, ev) {
      // console.log('tree drop 拖拽完成: ',draggingNode, dropNode, dropType, ev);
      // 将dropType对应成数字
      switch (dropType) {
        case 'before': 
          dropType = 0; 
          break;
        case 'after': 
          dropType = 1; 
          break;
        case 'inner': 
          dropType = 2; 
          break;
        default:  
          dropType = 0; 
          break;
      }
      let params = {
        affectedNode: {
          id: dropNode.data.id,
          parentId: dropNode.data.parentId,
          title:dropNode.data.title,
          ord: dropNode.data.ord,
          path: dropNode.data.path
        },
        dragNode: {
          id: draggingNode.data.id,
          parentId: draggingNode.data.parentId,
          title:draggingNode.data.title,
          ord: draggingNode.data.ord,
          path: draggingNode.data.path
        },
        type: dropType
      }
      moveDirectory(params)
        .then(res=>{
          console.log(res)
          // 更新节点数据

        })
        .catch(()=>{
          // 删除放置的节点
          this.$refs.tree.remove(draggingNode.data)
          // 节点位置还原
          draggingNode.parent = this.$refs.tree.getNode(draggingNode.data.parentId)
          this.$refs.tree.getNode(draggingNode.data.parentId).childNodes.splice(this.beforeDragNodeIndex, 0, draggingNode)
        })
},

6.某节点高亮

我的项目需求是点击了一个资源之后将它所在的目录高亮显示,当然了,如果大家的树不是懒加载的情况,那直接使用组件提供的setCurrentKey这个方法就可以了

如果有人跟我一样是懒加载,一定会发现个鸡肋的问题,就是有的节点还没加载子节点,如果高亮显示的是他的子节点,根本不会高亮显示的

解决思路:必须拿到需要高亮显示节点的父级层级关系,也就是它的父级是谁,它的父级的父级是谁,直到顶层,然后我们可以利用这个节点的层级信息,依次从顶点开始展开直到该节点,随后高亮显示该节点

来吧,代码来了

// 设置当前高亮(dirId:需要高亮显示的目录id也就是每个节点绑定的那个key   dirPath:节点层级关系,我这里是以/分隔开的字符串)
setCurrentKey(dirId, dirPath){
      let pathArr = dirPath.split('/')
      // 去掉数组首尾:首节点是空,尾节点是当前节点(同dirId)
      pathArr = pathArr.slice(1, pathArr.length - 1)
      // 展开节点的所有父级
      this.expandNodes(pathArr, 0, ()=>{
        // 节点展开之后触发高亮节点
        this.$refs.tree.setCurrentKey(dirId)
      })
    
/**
 * 循环展开节点
 * nodesArr:需要展开的节点数组
 * index:从第几个下标开始(为了方便函数递归使用)
 * expandCallback: 所有节点展开之后的回调
 */
expandNodes(nodesArr, index = 0, expandCallback){
      if(index < nodesArr.length){
        this.$refs.tree.getNode(nodesArr[index]).expand(()=>{
          index++
          if(index == nodesArr.length){
            expandCallback ? expandCallback() : ''
          }else{
            this.expandNodes(nodesArr, index, expandCallback)
          } 
        })
      }else{
        // 递归出口
      }
},

7.总结

 起关键作用的几个东西

  • getNode() : 根据 data 或者 key 拿到 Tree 组件中的 node,官网给了这个函数,自己去查一下就行
  • expand():  节点node对象的函数,展开指定节点,如果已经展开过,直接展开,如果没有展开过,先加载该节点的子节点,然后展开
  • Node节点:箭头指向的是我此次实践中常用到的哦,它里面的data就是我们从接口拿到的该节点的数据,parent是父节点的Node对象,...

8. 组件整体的代码

粘贴一下给大家,方便看的清楚

// 带有管理操作的目录树
<template>
  <div class="container-menu" :style="{height: viewHeight + 'px'}">
    <!-- 搜索区域 -->
    <div class="menu-header">
      <el-input
        v-model="filterText"
        placeholder
        id="input"
        size="mini"
        suffix-icon="el-input__icon el-icon-search"
        @keyup.enter.native="filterMenu(-1)"
      ></el-input>
    </div>
    <!-- 目录 -->
    <el-scrollbar class="scrollbar-container" wrapStyle="margin-bottom:0">
      <el-tree
        ref="tree"
        lazy
        :load="loadNode"
        node-key="id"
        :props="defaultProps"
        :highlight-current="true"
        :expand-on-click-node="false"
        :current-node-key="currentNodekey"
        :default-expanded-keys="defaultExpandKeys"
        draggable
        :allow-drop="allowDrop"
        :allow-drag="allowDrag"
        @node-drag-start="handleDragStart"
        @node-drop="handleDrop"
        @node-click="handleNodeClick">
        <div class="custom-tree-node flex-space-between" slot-scope="{ node, data }" >
          <div class="tree-icon">
            <icon-svg class="file" icon-class="file"></icon-svg>
          </div>
          <div class="tree-label">
            <span v-show="editDirId !== data.id">
              {{node.label}}
              <template v-if="data.num">({{data.num}})</template>
            </span>
            <el-input
              :ref="data.id"
              v-show="editDirId === data.id"
              v-model.trim="data.title"
              size="mini"
              maxlength="15"
              @keyup.enter.native="$event.target.blur"
              @blur="labelBlur(node)"
            ></el-input>
          </div>
          <!-- 添加、编辑、删除按钮 -->
          <div class="tree-options">
            <!-- 带子节点的节点 有刷新功能 -->
            <i v-if="!node.isLeaf" class="btn blue el-icon-refresh" @click.stop="refreshNode(node)"></i>
            <!-- 添加节点 -->
            <i class="btn blue el-icon-plus" @click.stop="addNode(node)"></i>
            <!-- 我的目录(id=-1)不能修改 -->
            <i v-if="data.id != -1" class="btn el-icon-edit" @click.stop="showInput(data.id, data.title)"></i>
            <!-- 我的目录(id=-1)不能删除 :aaa=" data.id"-->
            <i v-if="data.id != -1"  class="btn red el-icon-delete" @click.stop="deleteDir(node, data.id)"></i>
          </div>
        </div>
      </el-tree>
    </el-scrollbar>
  </div>
</template>

<script>
import { isArray } from 'utils/index'
import { mapGetters } from 'vuex'
import { 
  getChildernDirectoryById,
  insertDirectory,
  updateDirectory,
  deleteDirectoryById,
  moveDirectory
} from 'api/datameta/sourceRegister/index'

export default {
  name: 'menuWithManage',
  data () {
    return { 
      // 树状图默认配置
      defaultProps: {
          children: 'children',
          label: 'title',
          isLeaf:  function(data, node){
            return data.isLeaf == 'true' ? true : false
          }
      },
      // 当前选中的节点
      currentNodekey: '', 
      // 过滤文本
      filterText: '',
      // 编辑目录id:控制input框显示
      editDirId: '',  
      // 编辑目录名:记录旧目录名         
      oldDirName: '', 
      // 默认展开的节点的 key 的数组          
      defaultExpandKeys: ["-1"], 
      // 新增目录id的后缀: 用于新增时起的初始目录名不重复    
      dirIdSuff: 0,   
      // 节点拖拽前在父节点的位置下标 
      beforeDragNodeIndex: 0
    }
  },
  computed: {
    ...mapGetters(['viewHeight'])
  },
  methods: {
    // 获取目录列表
    getMenuList(parentId, success, error){
      getChildernDirectoryById({ 
          directoryId: parentId,
          dirName: this.filterText
        })
        .then(res => {
          // 获取"我的目录"子节点时, 更新"我的目录"的资源条数
          if(parentId == -1){
            this.$refs.tree.getNode(-1).data.num  = res.data.num
          }
          success ? success(res.data.dirInfo) : ''
        })
        .catch(res=>{
          error ? error(res) : ''
        })
    },
    
    // 点击节点的回调 node-click
    handleNodeClick (data, node) {
      this.$emit('chooseMenuItem', data, node)
    },
    
    // 子节点加载方法
    loadNode(node, resolve) {
      if (node.level === 0) {
          return resolve([{
            id: '-1',
            title: '我的目录', 
            path: '/-1',
            num: 0,
            isLeaf: false
          }]);
      }else{
        this.getMenuList(
          node.data.id, 
          data=>{
            resolve(data)
          },
          error=>{
            resolve([])
          }
        )
      }
    },
    
    // 允许放置的节点设置
    allowDrop(draggingNode, dropNode, type) {
      if (dropNode.data.id == -1) {
        return type === 'inner';
      } else {
        return true;
      }
    },

    // 允许拖拽的节点设置
    allowDrag(draggingNode) {
      return draggingNode.data.id != -1;
    },

    // 拖拽前: 保存被拖拽元素的下标
    handleDragStart(draggingNode, event){
      draggingNode.parent.childNodes.forEach((childNode, nodeIndex) =>{
        if(childNode.key == draggingNode.key){
          this.beforeDragNodeIndex = nodeIndex
          return
        }
      })
    },

    // 拖拽完成
    handleDrop(draggingNode, dropNode, dropType, ev) {
      // console.log('tree drop 拖拽完成: ',draggingNode.parent, dropNode.parent, dropType, ev);
      // 将dropType对应成数字
      switch (dropType) {
        case 'before': 
          dropType = 0; 
          break;
        case 'after': 
          dropType = 1; 
          break;
        case 'inner': 
          dropType = 2; 
          break;
        default:  
          dropType = 0; 
          break;
      }
      let params = {
        affectedNode: {
          id: dropNode.data.id,
          parentId: dropNode.data.parentId,
          title:dropNode.data.title,
          ord: dropNode.data.ord,
          path: dropNode.data.path
        },
        dragNode: {
          id: draggingNode.data.id,
          parentId: draggingNode.data.parentId,
          title:draggingNode.data.title,
          ord: draggingNode.data.ord,
          path: draggingNode.data.path
        },
        type: dropType
      }
      moveDirectory(params)
        .then(res=>{
          console.log(res)
          // 更新节点数据

        })
        .catch(()=>{
          // 删除放置的节点
          this.$refs.tree.remove(draggingNode.data)
          // 节点位置还原
          draggingNode.parent = this.$refs.tree.getNode(draggingNode.data.parentId)
          this.$refs.tree.getNode(draggingNode.data.parentId).childNodes.splice(this.beforeDragNodeIndex, 0, draggingNode)
        })
    },

    // 刷新指定节点
    refreshNode(node){
      node.loaded = false
      node.expand()
    },

    // 点击了添加子节点按钮
    addNode(node){
      node.expand(()=>{
        this.dirIdSuff = 0;
        let newDirName = this.getOnlyDirName('新建目录', node.childNodes)
        let order = node.childNodes.length > 0 ? node.childNodes[node.childNodes.length-1].data.ord + 1 : 0
        let newChild = { 
          title: newDirName, 
          isLeaf: "true",
          ord: order,
          num: 0
        } 
        
        insertDirectory({
          "parentId": node.data.id,
          "path": node.data.path,
          "title": newDirName,
          "ord": order
        })
        .then(res => {
          newChild.parentId = res.data.parentId
          newChild.id = res.data.id
          newChild.path = res.data.path
          this.$refs.tree.append(newChild, node)
          
          this.showInput(res.data.id, newChild.title)
        })
      })
    },

    // 点击了编辑按钮
    showInput(id, title){
      this.oldDirName = title
      this.editDirId = id
      this.$nextTick(() => {
        this.$refs[id].focus()
      })
    },

    // 点击了删除节点
    deleteDir(node, dirId){
      this.$confirm('确定删除[ '+node.data.title+' ]吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
      .then(() => {
        deleteDirectoryById({ directoryId: dirId })
          .then(res=>{
            this.$message({
              type: 'success',
              message: '删除成功!'
            })
            this.$refs.tree.remove(node)
          })
      });
    },
    
    // input失去焦点(编辑目录名)
    labelBlur (node) {
      let data = node.data
      this.editDirId = ''
      // 名字相等的时候不用改
      if (data.title === this.oldDirName) return
      // 检查名字是否重复
      let sameName = isArray(node.parent.childNodes) ? 
        node.parent.childNodes.some( childNode => childNode.data.title===data.title && childNode.data.id!==data.id )
        :
        false
      if(sameName) {
        data.title = this.oldDirName
        this.$message({
          type: 'error',
          message: '同目录不允许同名哦!'
        })
        return
      }

      // 目录名称校验

      // 修改目录,调用接口
      updateDirectory({
        "id": data.id,
        "title": data.title
      })
      .then(res => {
        this.$message({ type: 'success', message: '修改成功!' })
      })
      .catch(() => {
        data.title = this.oldDirName
      })
    },
    
    // 过滤函数(递归展开所有符合规则的节点)
    filterMenu(nodeId = -1){
      // 过滤文本为空时,刷新顶级节点
      if(this.filterText.trim() == '') {
        let topNode = this.$refs.tree.getNode(-1)
        topNode.childNodes = []
        topNode.loaded = false
        topNode.expand()
        return
      }
      let node = this.$refs.tree.getNode(nodeId)
      // 重新展开该节点
      console.log(nodeId)
      node.loaded = false
      node.expand(()=>{
        // 检查子元素是否有非叶子结点
        node.childNodes.forEach(item => {
          if(item.data.isLeaf == 'false'){
            // 递归处理含有子节点的节点
            this.filterMenu(item.data.id)
          }else{
            // 递归出口
          }
        });
      }) 
    },
    
    // 寻找一个合适的目录名
    getOnlyDirName (title, arr) {
      let dirName = title + this.dirIdSuff
      isArray(arr)  ? '' : arr = []
      if(arr.find(val => val.data.title === dirName)){
        this.dirIdSuff++
        return this.getOnlyDirName(title, arr)
      }else{
        this.dirIdSuff = 0
        return dirName
      }
    },
   
    // 寻找一个合适的目录id
    getOnlyDirId (data){
      let dirId = data.id + '' + this.dirIdSuff
      let arr = isArray(data.children) ? data.children : []
      if(arr.find(val => val.id == dirId)){
        this.dirIdSuff++
        return this.getOnlyDirId(data)
      }else{
        this.dirIdSuff = 0
        return dirId
      }
    },
    
    // 设置当前高亮
    setCurrentKey(dirId, dirPath){
      let pathArr = dirPath.split('/')
      // 去掉数组首尾:首节点是空,尾节点是当前节点(同dirId)
      pathArr = pathArr.slice(1, pathArr.length - 1)
      // 展开节点的所有父级
      this.expandNodes(pathArr, 0, ()=>{
        // 节点展开之后触发高亮节点
        this.$refs.tree.setCurrentKey(dirId)
      })
    },

    /**
     * 循环展开节点
     * nodesArr:需要展开的节点数组
     * index:从第几个下标开始(为了方便函数递归使用)
     * expandCallback: 所有节点展开之后的回调
     */
    expandNodes(nodesArr, index = 0, expandCallback){
      if(index < nodesArr.length){
        this.$refs.tree.getNode(nodesArr[index]).expand(()=>{
          index++
          if(index == nodesArr.length){
            expandCallback ? expandCallback() : ''
          }else{
            this.expandNodes(nodesArr, index, expandCallback)
          } 
        })
      }else{
        // 递归出口
      }
    },
  }
}
</script>
<style rel='stylesheet/scss' lang='scss' scoped>
.container-menu{
  .menu-header{
    border-bottom: 1px solid #e8e8e8;
    /deep/.el-input__inner{
      height: 32px;
      line-height: 32px;
      border: 0;
    }
  }
  .scrollbar-container{
    height: calc(100% - 46px);
    padding-top: 7px;
  }
}

.custom-tree-node {
  width: calc(100% - 24px);
  font-size: 12px;
  line-height: 24px;
  align-items: center;
  .tree-icon {
    width: 20px;
    .file {
      width: 20px;
      font-size: 20px;
      vertical-align: text-bottom;
    }
  }
  
  .tree-label {
    // 100% - 50px - 20px
    width: calc(100% - 70px);
    // 1.先强制一行内显示文本
    white-space: nowrap;
    // 2.超出部分隐藏
    overflow: hidden;
    // 3.文字用省略号代替
    text-overflow: ellipsis;
    height: 24px;
    line-height: 24px;
    .el-input {
      /deep/.el-input__inner {
        height: 21px;
      }
    }
  }
  .tree-options{
    display: flex;
    justify-content: flex-end;
    opacity: 0;
    width: 50px;
    margin-right: 6px;
  }
  .btn {
    font-size: 10px;
    font-weight: bold;
  }
  .btn:nth-child(odd){
    margin: 0 4px;
  }
  .blue {
    color: #409eff;
  }
  .red {
    color: #f56c6c;
  }
}

// 节点hover,操作按钮显示
.custom-tree-node:hover .tree-options{
  opacity: 1 !important;
}
</style>

有啥更好的解决办法,还望大家不吝赐教!同时也欢迎指出问题!

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值