el-tree树形控件

 官网:Element - The world's most popular Vue UI framework

 应用场景:

        1、自定义树节点内容,鼠标悬浮树节点,右侧出现节点增删改操作;

        2、树形控件增加纵向滚动条;    

        3、关键字过滤树节点数据;

        4、节点文本数据自适应宽度且溢出省略;

        5、默认展开第一个节点;

 代码如下:

​
   <el-scrollbar class="treeWrap">
    <div class="treeSearch">
        <el-input placeholder='请输入关键词' v-model="keywords"></el-input>
     </div>
     <el-tree
         class="el-tree"
         ref="treeRef"
         :data="treeData"
         node-key="id"
         :props="defaultProps"
         :highlight-current="true"
         :expand-on-click-node="false"
         :default-expanded-keys="defaultExpandedIdArr",
         :filter-node-method="filterNode"
         @node-click="nodeClick"
      >
         <div
            class="custom-tree-node"
            slot-scope="{ node, data }",
            @mouseenter="labelHover($event, node, data)"
            @mouseleave="labelHoverLeave($event, node, data)"
         >
            <el-tooltip
                effect="dark",
                :content="node.label",
                placement="top-start",
                :open-delay="1000"
            >
                <span class="labelName">{{ node.label}}</span> 
            </el-tooltip>
            <span class="showIcon" v-show="node.showIcon">
                <i class="iconfont icon-xinjianwenjianjia"  
                    @click.stop="iconClick(data, node, 1)">
                </i>
                <i class="iconfont icon-bianji"  
                    @click.stop="iconClick(data, node, 2)">
                </i>
                <i class="iconfont icon-lajitong"  
                    @click.stop="iconClick(data, node, 3)">
                </i>
                <i class="iconfont icon-icon-shuju3"  
                    @click.stop="iconClick(data, node, 4)">
                </i>
            </span>
        </div>
     </el-tree>
    </el-scrollbar>

​

el-scrollbar:el-scrollbar滚动条组件在官网文章中没有介绍源码中是有的,要注意的是el-scrollbar需要指定高度,该元素的内容就是滚动条要包裹的内容;

el-tree的属性和事件官网都有注释,在这里主要解释一下几点:

        node-key:树节点用来作为唯一标识的属性,正常情况下设置数据的id; 

        filter-node-method:对树节点筛选执行的方法; 

        node-click:节点被点击时的回调事件;

        slot-scope="{ node, data }":自定义树节点内容;

        default-expanded-keys:默认展开的节点的key数组;

        setCurrentKey:el-tree控件自身方法,参数(key) 为被选节点的 key,若为 null 则取消当前高亮的节点,通过 key 设置某个节点的当前选中状态,使用此方法必须设置 node-key 属性

 data定义的数据:

data() {
    return {
      currentNode: null,//当前节点数据
      treeData: [],//树节点数据
      defaultProps: {//配置选项
        children: "children",//子树为节点对象的children属性值
        label: "name",//节点标签为节点对象的name属性值
      },
    }
  },

关键字过滤树节点数据事件: watch监控关键字变化执行过滤事件,返回的数据为符合条件的节点树结构;

watch: {
    keywords(val) {
      this.$refs.treeRef.filter(val);
    },
  },
filterNode(value, data, node) {
   if (!value) return true;
   // return node.label.indexOf(value) !== -1;
//此处过滤只返回符合条件的节点,之后代码返回符合条件的节点树结构,根据需求自行选择
   let arr = [];
   this.getReturnNode(node,arr,value)
   let result = false
   arr.forEach(v=>{
      result = result || v
   })
   return result
},
getReturnNode(node,arr,value){
   let pass = node.data&&node.label.indexOf(value) !== -1
   pass? arr.push(pass) : ''
   if(!pass && node.level != 1 && node.parent){
     this.getReturnNode(node.parent,arr,value)
    }
 },

 鼠标移入移出显示操作项事件:

labelHoverLeave(event, node, data) {
  this.$set(node, "showIcon",false );
},
labelHover(event, node, data) {
  this.$set(node, "showIcon", true);
},

树节点点击事件:回调参数有event,该节点对应对象数据,节点对应的Node,节点组件本身数据

nodeClick(data, node, item) {
    //根据需求自行写入
}

节点操作项事件:

iconClick(data, node, index) {
      this.currentNode = node
      if (index == 1) { // 添加子数据
        this.$prompt('请输入节点名称', '添加子节点', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          inputValue: '',
          inputPattern: /.{3}$/,
          inputErrorMessage: '请输入节点名称,不少于3个字'
        }).then(({ value }) => {
          //调取接口执行添加事件
          this.$message.success('添加成功!')
          this.getTreeData()//添加成功之后更新树控件数据
        }).catch(() => {});
      } else if (index == 2) { // 编辑
        this.$prompt('请输入节点名称', '编辑子节点', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          inputValue: node.label,
          inputPattern: /.{3}$/,
          inputErrorMessage: '请输入节点名称,不少于3个字'
        }).then(({ value }) => {
          //调取接口执行编辑事件
          this.$message.success('编辑成功!')
          this.getTreeData()//编辑成功之后更新树控件数据
        }).catch(() => {});
      } else if (index == 3) { // 删除
        if (node.childNodes.length > 0) {
          this.$message.warning("存在下级子设施,无法删除!");
          return false; 
        }
        this.$confirm('确认删除该节点?', '提示信息').then(() => {
          //调取接口执行删除事件
          this.$message.success('删除成功!')
          this.currentNode = null
          this.getTreeData()//删除成功之后更新树控件数据
        }).catch(()=>{})
      }else{} 
    },

默认展开第一个节点数据:default-expanded-keys和setCurrentKey都可以实现该效果,且刷新数据后需要保留之前展开状态

async getTreeData () {
  const { result } = await this.$api[xxx]()//调取接口树控件数据
  if (!result) {
     this.$message.error('数据错误,请联系管理员!')
     return
  }
  this.treeData = result || []
  let id = this.currentNode?.data?.id?
this.currentNode.data.id: this.treeData.length>0? 
  this.findTree(this.treeData).id : -1;
//编辑新增刷新数据保留之前节点展开状态
  this.$nextTick(() => {
     this.$refs.treeRef.setCurrentKey(id)
//通过 keys 设置目前勾选的节点,使用此方法必须设置 node-key 属性,
//也可以根据default-expanded-keys设置
  });
},
findTree(array) {//递归返回第一个树节点的数据
  if (!array[0].children||array[0]?.children?.length==0) {
    return {
      id:array[0].id,
      name:array[0].name,
     } 
   } else {
     return this.findTree(array[0].children);
   }
},

css样式设置:

    .treeWrap{
        height: 100%;
        width: 260px;
        ::v-deep(.el-scrollbar__bar.is-horizontal){
          display: none;
        }
        ::v-deep .el-scrollbar__wrap {
          overflow-x: hidden !important;
        }
        .treeSearch{
            width:250px;
            padding:10px 0px 10px 8px;
            position:fixed;
            background:#fff;
            z-index:2000
         }
        .el-tree{
          padding-top: 60px;
          .custom-tree-node{
            flex: 1; 
            min-width: 0;
            display: flex; 
            height: 32px;
            align-items: center;
            justify-content: space-between;
            padding-right: 8px;
            height: 100%;
            box-sizing: border-box;
            .showIcon {
              right: 10px;
              padding-right: 2px;
              z-index: 1000;
              background-color: #f0f7ff;
            }
            .labelName{
              flex: 1;
              white-space: nowrap;
              overflow: hidden;
              text-overflow: ellipsis;
              padding: 2px 0px !important;
              box-sizing: border-box;
            }
          }
        }
      }

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值