Elementui树形列表控件tree-box

效果图(在vue2项目开发中,实现了树形列表查看及筛选等交互,用清晰的层级结构展示信息)

 

开发步骤及代码,来喽!!无脑copy

1、组件基本框架

  DeviceTree 是基于 Vue.js 和 Element UI 构建的树形组件。通过 el-tree 组件显示树状结构。组件的外部可通过传递 props 来控制是否显示复选框、设备过滤等特性。

核心字段和方法:
  • treeData: 保存树的节点数据。
  • currentKey: 记录当前点击的节点。
  • defaultProps: 定义树节点的子元素 (children),用于指定树的层次结构。
  • handleNodeClick: 响应节点点击事件,将点击的节点信息传递给父组件。
  • handleNodeExpand: 处理节点展开事件,防止同级节点全部展开,优化用户体验。

2、树形列表数据获取 

        组件在 created 钩子中调用 getTreeData 方法,从服务器获取树形结构数据,并将其格式化为适合 el-tree 的数据格式。(可以使用axios、ajaxs,我使用的是$http.post)

const res = this.$http.post("/后端接口", {userID: userid},{headers:headers});

      res.then((ret) => {

        var data = ret.data.data;

        this.treeData = data.map(line => {

              return {

                NodeName: line.lineName, 

                id: line.lineID,

                type: line.type,

                icon: 'el-icon-location',

                Children: line.areaList.map(area => ({

                  NodeName: area.areaName,  

                  id: area.areaID,

                  type: area.type,

                  icon: 'el-icon-location-outline'

                }))

              };

            });      

      });

3、组件交互功能

3.1过滤功能

  • 使用 el-tree 组件的 filter-node-method 实现对树节点的过滤。filterText 绑定到输入框的内容,当输入内容发生变化时,会触发树节点的过滤。

3.2 节点选择

  • getCheckedNodes: 获取用户选择的复选框节点,用于在用户勾选复选框后,获取所选中的节点信息。
  • clearChecked: 清空所有勾选的节点。

3.3树节点的渲染

        通过 eventRender 自定义树节点的渲染内容,显示节点的图标和名称,并根据需要是否显示复选框。

4、外部接口用于供父组件调用或监听

  • selectEquipTree: 当用户点击某个节点时,触发该事件,向父组件传递所选节点的信息。
  • updateData: 更新树的数据,供外部组件调用,重新渲染树结构。

5、代码来喽

<template>

  <div id="device-tree">

    <div class="title">线路列表<span ref="spanRef"></span></div>

    <el-input placeholder="输入关键字进行过滤" v-model="filterText" size="small">

    </el-input>

    <div class="tree-box">

      <el-tree

        :data="treeData"  

        :props="defaultProps"

        ref="deviceTree"

        node-key="id"

        :default-expanded-keys="[currentKey]"

        :current-node-key="currentKey"

        :filter-node-method="filterNode"

        :render-content="eventRender"

        @node-click="handleNodeClick"

        @node-expand="handleNodeExpand">

        <span class="span-ellipsis" slot-scope="{ data }">

          <i :class="data.icon" style="color: darkseagreen"></i>

          <span class="span-tip" :title="data.linename">

            {{ data.linename }}

          </span>

        </span>

        <span class="span-ellipsis" slot-scope="{ data }">

          <i :class="data.icon" style="color: darkseagreen"></i>

          <span class="span-tip" :title="data.AreaName">

            {{ data.AreaName }}

          </span>

        </span>

      </el-tree>

    </div>

  </div>

</template>

<script>

export default {

  name: "DeviceTree",

  data() {

    return {

      filterText: "",

      treeData: [],

      currentKey: 1,

      type: '',

      defaultProps: {

        children: "Children",

        label: "NodeName",

        isLeaf: "leaf",

      },

    };

  },

  props: {

    parentNoclick: {

      default: true,

      type: Boolean,

    },

    isShowEquip: {

      default: true,

      type: Boolean,

    },

    equipFilter: {

      default: "All",

      type: String,

    },

    isShowCheck: {

      default: false,

      type: Boolean,

    },

    isShowRedCamera: {

      default: false,

      type: Boolean,

    },

    isShowTempreature: {

      default: false,

      type: Boolean,

    },

    props: {

      equipData: {

        type: Array,

        default: () => [],

      },

    },

  },

  watch: {

    filterText: function (val) {

      this.$refs.tree.filter(val);

    },

  },

  created() {

    this.getTreeData();

  },

  methods: {

    filterNode(value, data) {

      if (!value) return true;

      return data.NodeName.indexOf(value) !== -1;

    },

    handleNodeClick(data, node) {

      this.currentKey = data.id;

      this.type = data.type;

      this.$emit("selectEquipTree", data);

    },

    handleNodeExpand(data, node) {

      if (node.parent.data.NodeType == 1) {

        var nodes = node.parent.childNodes;

        nodes.forEach((n) => {

          if (n.id != node.id) n.expanded = false;

        });

        this.$refs.tree.setCheckedKeys([], true);

      }

    },

    updateData(newData) {

      this.equipData = newData;  // 更新树形组件的数据

      this.refreshTree();  // 假设有一个方法用于刷新树

    },

    refreshTree() {

      this.getTreeData();

    },

    // 获取树形结构

    getTreeData() {

      const token = localStorage.getItem('token')

      const userid = localStorage.getItem('userid');  

      const headers = {

          'Authorization': `Bearer ${token}`

      };

      const res = this.$http.post("/api/Area/GetAreaTreeList", {userID: userid},{headers:headers});

      res.then((ret) => {

        var data = ret.data.data;

        this.treeData = data.map(line => {

              return {

                NodeName: line.lineName,

                id: line.lineID,

                type: line.type,

                icon: 'el-icon-location',

                Children: line.areaList.map(area => ({

                  NodeName: area.areaName,  

                  id: area.areaID,

                  type: area.type,

                  icon: 'el-icon-location-outline'

                }))

              };

            });

       

      });

    },

    eventRender(h, { node, data, store }) {

      if (this.isShowCheck) {

        node.isLeaf = false;

        if (data.NodeType == 1) {

          node.isLeaf = true;

        }

      }

      return (

        <span class="span-ellipsis">

          <i class={data.icon} style="color: darkseagreen"></i>

          <span class="span-tip" title={data.NodeName}>

            {data.NodeName}

          </span>

        </span>

        // {}

      );

    },

    getCheckedNodes() {

      var keys = this.$refs.tree.getCheckedKeys(true);

      let checkedNodes = [];

      keys.forEach((key) => {

        var node = this.$refs.tree.getNode(key);

        checkedNodes.push(node);

      });

      return checkedNodes;

    },

    clearChecked() {

      this.$refs.tree.setCheckedKeys([], true);

    },

  },

};

</script>

<style lang="less">

#device-tree {

  width: 260px;

  padding-left: 10px;

  height: 100%;

  .title {

    color: #1bc3de;

    font-size: 18px;

    border-left: 3px solid #489fff;

    margin-bottom: 10px;

    padding-left: 10px;

    text-align: left;

    span {

      color: #fff;

    }

  }

  .el-input {

    margin-bottom: 10px;

    input {

      width: 240px !important;

    }

  }

  .tree-box {

    height: calc(100% - 34px - 42px);

    overflow: hidden;

    overflow-y: visible;

    .el-input {

      margin-bottom: 10px;

      input {

        width: 240px !important;

      }

    }

  }

  .el-tree {

    background: transparent;

    color: #c0cbe0;

    margin-right: 10px;

    /deep/.is-current {

      background: #13386c;

      > .el-tree-node__content {

        background: #13386c;

      }

    }

    .span-ellipsis {

      display: block;

      overflow: hidden;

      white-space: nowrap;

      text-overflow: ellipsis;

      font-size: 16px;

      font-weight: bold;

    }

    .el-tree-node__content:hover {

      background-color: rgba(20, 57, 109, 0.3);

    }

    .el-tree-node {

      .is-current {

        background-color: #13386c;

      }

    }

    .el-tree-node {

      .is-leaf + .el-checkbox .el-checkbox__inner {

        display: inline-block;

        border: 1px solid #489fff;

        background-color: #3242654d;

      }

      .el-checkbox .el-checkbox__inner {

        display: none;

        border: 1px solid #489fff;

        background-color: #3242654d;

      }

    }

    .el-tree-node:focus > .el-tree-node__content {

      background-color: #13386c;

    }

    .el-tree-node__label {

      font-size: 16px;

      font-weight: bold;

    }

    .el-checkbox__input.is-checked .el-checkbox__inner {

      background-color: #409eff;

    }

  }

}

</style>

6、总结

        这个组件通过 el-tree 组件展示树形结构设备列表,支持节点点击、展开、过滤等功能,并通过多种方法和事件与父组件进行交互。数据通过后端接口获取并动态更新树结构,具有良好的用户体验和扩展性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值