• antd——使用a-tree组件实现 检索+自动展开+自定义增删改查功能——技能提升


    场景

    之前写后台管理系统时,遇到一个下面的需求,下面是最终完成的效果图。
    在这里插入图片描述
    实现的功能有:

    1. 下拉 选择不同的类型——就是一个普通的select组件,下面并不做介绍

    2. 通过关键字可以进行tree树形结构的筛选,然后将筛选后的内容自动展开

    在这里插入图片描述

    3. tree组件中,每一条数据,鼠标移入后展示 增/删/改 图标,点击有对应的功能

    在这里插入图片描述

    下面直接上代码

    一:tree组件的使用

    <a-tree
     :treeData="treeData"
      ref="treeNode"
      v-if="treeData"
      :showIcon="false"
      class="tree-list"
      :defaultExpandAll="true"
      :expandedKeys.sync="defaultExpandedKeys"
      tree-default-expand-all
      :replaceFields="replaceFields"
    >
    </a-tree>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    1. treeData :tree组件的数据源
    2. ref:相当于id,可以通过此参数获取到dom结构
    3. v-if:只有当有数据源的时候才显示组件
    4. showIcon:设置成false,就不会展示默认的tree组件图标了,此时可以通过自定义图标的形式来展示自定义的效果了
    5. class="tree-list":因为我进行了自定义的样式处理,此时添加一个类名用于与其他tree组件区分
    6. defaultExpandAll:设置成true,默认展开所有节点,也可以通过下面的expandedKeys来指定展开的节点
    7. expandedKeys:异步指定要展开的节点,用于筛选后所有符合条件的数据的展开
    8. replaceFields:当数据源给定的数据结构与期望的结构不符时,可以通过此参数进行设置。
    我这边的配置如下: 
    replaceFields: {
        children: 'children',
        title: 'title',
        key: 'key',
        value: 'subTitle',
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    二:使用插槽实现自定义组件结构

    <a-icon slot="switcherIcon" type="caret-down" />
    <template slot="custom" slot-scope="item">
      <div @mouseenter="mouseenter(item)" style="position: relative">
        <span
          style="
            height: 30px;
            width: 70%;
            display: flex;
            align-items: center;
          "
        >
          <a-icon
            type="home"
            theme="filled"
            style="
              height: 30px;
              line-height: 30px;
              padding-right: 5px;
            "
            v-if="item.slots.Code"
          />
          <a-icon
            type="user"
            style="
              height: 30px;
              line-height: 30px;
              padding-right: 5px;
            "
            v-if="item.slots.UserId"
          />
          <span
            style="
              height: 30px;
              display: inline-block;
              max-width: 80%;
              overflow: hidden;
              text-overflow: ellipsis;
              padding-right: 5px;
            "
            >{{ item.title }}</span
          >
          <span
            style="
              height: 30px;
              display: inline-block;
              max-width: 80%;
              overflow: hidden;
              color: #f90;
              font-weight: bold;
              height: 30px;
            "
          >
            <span v-if="item.slots.IsSecondary"
              >[]</span
            >
            <span v-if="item.slots.IsLeader"
              >[]</span
            >
          </span>
        </span>
        <a-space
          @click.stop
          v-if="currentId == item.key"
          style="position: absolute; right: 25px; top: 0"
        >
          <a-icon
            type="plus-square"
            style="color: green"
            @click.stop="handleAdd(item)"
            v-if="item.key.indexOf('U') == -1"
          />
          <a-icon type="edit" @click.stop="handleEdit(item)" />
          <a-icon
            type="delete"
            @click.stop="handleDel(item)"
            style="color: red"
            v-if="item.key.indexOf('U') == -1"
          />
        </a-space>
      </div>
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    三:数据结构需要转化成 scopedSlots自定义的插槽

    在这里插入图片描述
    原有的数据结构:
    在这里插入图片描述
    将上面的数据结构通过下面的方法进行转化。

    filterTreeData(arr) {
      arr.forEach((item) => {
        item['scopedSlots'] = { title: 'custom' };
        item.Id = item?.slots?.Id;
        item.Name = item?.slots?.Name;
        item.selectable = true;
        item.subTitle = item.title + '(' + item.key + ')';
        this.$forceUpdate();
        if (item.children) {
          this.filterTreeData(item.children);
        }
      });
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    最终转化后的数据结构如下:
    在这里插入图片描述
    此时就可以通过上面前两步的设置进行正常渲染了。

    四:监听关键字的检索

    4.1 节流检索关键字

    //先定义一个定时器,然后在指定时间内,默认是200毫秒,如果发生变化,则清理定时器,重新定时
    debounce(callback, delay = 200) {
      clearTimeout(this.timeout);
      this.timeout = setTimeout(() => {
        callback();
      }, delay);
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4.2 input组件作为输入框

     <a-input
      style="margin-top: 8px; margin-bottom: 8px"
      v-model="searchValue"
      placeholder="请输入关键字"
      @change="onChange($event.target.value)"
      allowClear
    />
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4.3 监听input的change事件

    onChange(value) {
      this.defaultExpandedKeys = [];
      if (value) {
        this.debounce(() => {
          //此时需要根据value关键字,从treeData数据源中查找对应的数据,将key存放到defaultExpandedKeys数组中,就可以实现自动展开功能了。
        });
      } else {
        this.treeData = JSON.parse(JSON.stringify(this.originTreeData));
      }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4.4 通过XEUtiles.searchTree实现 多层对象数组的检索

    this.treeData = XEUtiles.searchTree(
      this.treeData,
      (item) => {
        if (item.title.toLowerCase().indexOf(value.toLowerCase()) > -1) {
          if (item.parent) {
            this.defaultExpandedKeys.push('S-' + item.parent);
          }
          this.defaultExpandedKeys.push(item.key);
          return true;
        } else {
          return false;
        }
      },
      { children: 'children' }
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    4.5 npm install xe-utils --save——我这边安装的版本是3.5.6

    "xe-utils": "^3.5.6"
    
    • 1

    4.6 局部页面引入xe-utils

    const XEUtiles = require('xe-utils');

    xe-utils使用文档说明:https://vxetable.cn/xe-utils/#/

    在这里插入图片描述
    入参:(数据源,查找条件,children的字段可以自定义)。

    可以将符合条件的数据,每一层的父级都找出来。

    具体的使用原理我没有研究,但是不用自己一层层遍历循环,还是很好的。

    五:鼠标移入

    mouseenter(item) {
      this.currentId = item.key;
    },
    
    • 1
    • 2
    • 3

    通过currentId参数与数据源中的key匹配,相同的则展示对应的图标。

    完成!!!

  • 相关阅读:
    js array数组json去重
    拼多多根据ID取商品详情 API
    Python版本机访问GEE,CoLab配置
    软件测试基本概念(1)
    解读TLS协议、CA认证中的非对称加密
    Linux虚拟机 & Docker 安装 RabbitMQ
    【干货技巧】最新 Java 后端面试系列干货,都在这了!
    编译安装并刷写高通智能机器人SDK
    webstorm 创建express项目
    【JS】数据结构之队列
  • 原文地址:https://blog.csdn.net/yehaocheng520/article/details/128032597