VUE el-tree组件左边勾选,右边清除交互问题

 更新时间:2023年04月23日 10:46:30   作者:爱吃炸鸡的杰  
这篇文章主要介绍了VUE el-tree组件左边勾选,右边清除交互问题,具有很好的参考价值,希望对大家有所帮助。

el-tree组件左边勾选,右边清除交互

需求

使用el-tree组件,左边可以勾选节点,右边展示已经勾选的节点。

效果

代码实现

<template>
  <div class="treeWrapper">
    <div class="leftView">
      <el-input placeholder="请输入内容" v-if="relationTree.length" v-model="filterTreeName" @change="filterChange"/>
      <el-checkbox v-if="relationTree.length" class="select-box" v-model="menuNodeAll"
                   @change="handleCheckedTreeNodeAll($event)">全选
      </el-checkbox>
      <el-tree :data="relationTree" show-checkbox node-key="id" ref="tree" :props="defaultProps" @check="hanldTreeCheck"
               default-expand-all :filter-node-method="filterNode" :default-checked-keys="checkedKeys">
      </el-tree>
    </div>
    <div class="rightView">
      <header>
        <span>已选择 {{ checkList.length }} 个</span>
        <span @click="removeRightTreeAll">全部清除</span>
      </header>
      <div class="checkedItem" v-if="checkList.length">
        <li v-for="(m, i) in checkList" :class="['align-center','justify-between',m.checkFlag ? 'mark':'']" :key="i">
          <p>{{ m.name }}</p>
          <svg-icon icon-class="deleteTreeItem" @click="tagClose(m, i)"/>
        </li>
      </div>
      <div class="right-nodata f_c_m" v-else>暂无数据</div>
    </div>
  </div>
</template>
<script>
export default {
  name: "baseTree",
  props: {
    relationTree: {
      type: Array,
      default: () => [],
    },
    checkedKeys: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      filterTreeName: "",
      menuNodeAll: false,
      defaultProps: {
        children: "relationResps",
        label: "name",
      },
      // 选中机器人
      checkList: [],
      checkDataList: [],
    };
  },
  mounted() {},
 
  methods: {
    filterNode(value, data) {
      if (!value) {
        return true;
      }
      return data.name.includes(value);
    },
    // 过滤
    filterChange() {
      this.$refs.tree.filter(this.filterTreeName);
    },
    // 全部清除
    removeRightTreeAll() {
      this.checkList = [];
      if (this.menuNodeAll) {
        this.menuNodeAll = !this.menuNodeAll;
      }
      const parentCheckedLength = this.$refs.tree.getCheckedKeys().length;
      if (parentCheckedLength !== 0) {
        this.$refs.tree.setCheckedNodes([]);
      }
      this.checkDataList = [];
      this.$emit("treeclick", this.checkDataList);
    },
    // 全选
    handleCheckedTreeNodeAll(data) {
      if (this.menuNodeAll) {
        //如果是当前值是全选,依次遍历节点设置勾选,同时过滤的disabled为true的
        // 深度遍历
        let stack = [...this.relationTree],
          node;
        while ((node = stack.shift())) {
          console.log(node.id);
          this.$refs.tree.setChecked(node.id, true, true);
          // 如果有子元素的话进行压栈操作
          if (node.children) stack.unshift(...node.children);
          this.checkList = this.$refs.tree.getCheckedNodes(true, false);
          this.hanldTreeCheck(this.$refs.tree.getCheckedNodes(this.checkList));
        }
      } else {
        //当前值不是全选,设置勾选列表为空
        this.$refs.tree.setCheckedKeys([]);
        this.checkList = [];
        this.$emit("treeclick", this.checkList);
      }
    },
    // 当tree 复选框被点击的时候触发
    hanldTreeCheck(data) {
      const childNodeList = this.$refs.tree.getCheckedNodes(true, false);
      this.checkList = childNodeList;
      this.checkDataList =
        (childNodeList.length &&
          childNodeList.map((instance) => {
            // 机器人
            const {
              id: equipmentId,
              name: equipmentName,
              parentId: instanceParentId,
              checkFlag: checkFlag,
            } = instance;
            // 门店
            const {
              id: storeId,
              name: storeName,
              parentId: instanceStoreParentId,
            } = this.$refs.tree.getNode(instanceParentId).data;
            // 公司
            const {id: companyId, name: companyName} =
              this.$refs.tree.getNode(instanceStoreParentId).data;
            return {
              storeId,
              storeName,
              equipmentId,
              equipmentName,
              companyId,
              companyName,
              checkFlag,
            };
          })) ||
        [];
      this.$emit("treeclick", this.checkDataList);
    },
 
    // 右侧组件点击“关闭”按钮触发
    tagClose(item, index) {
      // 在已选中项的下标中删除
      this.checkList.splice(index, 1);
      if (this.checkDataList.length) {
        this.checkDataList.splice(index, 1);
        this.$emit("treeclick", this.checkDataList);
      }
      // 在tree树控件中更改选中状态.
      //setChecked  接收三个参数,1. 勾选节点的 key 或者 data 2. boolean 类型,节点是否选中 3. boolean 类型,是否设置子节点 ,默认为 false
      this.$refs.tree.setChecked(item.id, false, true);
      // 重新计算已选中树形节点
      this.hanldTreeCheck();
    },
  },
};
</script>
 
<style lang="scss" scoped>
.treeWrapper {
  overflow: hidden;
  display: grid;
  grid-template-columns: 50% 50%;
  grid-auto-rows: 336px;
  margin: 10px auto;
  width: 100%;
  /* height: 336px; */
  border-radius: 6px;
  border: 1px solid #dbdbdb;
 
  .leftView {
    display: flex;
    flex-direction: column;
    /* width: 100%; */
    .el-tree {
      height: 100%;
    }
 
    .select-box {
      display: flex;
      justify-content: space-between;
      flex-direction: row-reverse;
      margin-top: 10px;
      padding: 0 18px 0 10px;
 
      .el-checkbox__label {
        font-size: 10px;
        font-weight: bold;
        color: #222222;
      }
    }
 
    .el-input {
      margin: 10px auto 0;
      width: 85% !important;
    }
 
    .el-tree {
      border: none !important;
      /* height: 100%; */
      overflow: overlay;
 
      .el-tree-node__content {
        padding-right: 10px !important;
 
        .el-checkbox {
          order: 2;
          flex: 1;
          text-align: right;
        }
 
        .custom-tree-node {
          order: 1;
 
          > span {
            display: block;
            max-width: 120px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
          }
        }
      }
 
      > .el-tree-node > .el-tree-node__content {
        padding-left: 10px !important;
      }
    }
  }
 
  .rightView {
    /* flex-basis: 50%; */
    position: relative;
    display: flex;
    flex-direction: column;
    padding: 0 0 0 18px;
    /* width: 100%; */
    border-left: 1px solid #dbdbdb;
 
    > header {
      display: flex;
      justify-content: space-between;
      margin: 16px 0 12px 0;
      padding-right: 10px;
      font-size: 10px;
 
      > span:nth-child(1) {
        color: #222222;
      }
 
      > span:nth-child(2) {
        color: #592c82;
        cursor: pointer;
      }
    }
 
    .checkedItem {
      height: 100%;
      overflow: overlay;
 
      > li {
        height: 26px;
        margin-right: 18px;
      }
 
      .mark {
        color: red;
      }
    }
  }
 
  .right-nodata {
    color: #909399;
    position: absolute;
    left: 50%;
    top: 60%;
    transform: translate(-50%, -50%);
  }
}
</style>

vue el-tree延时过滤

最近做了一个项目,把SQL服务器,数据库,表的结构呈现在el-tree内,以便作数据表和字段的描述维护。

这里写图片描述

el-tree获取数据库数据,前端呈现分层后,如何快速的找出一个节点,根据饿了么官方文档,el-tree有一个过滤的功能。 :filter-node-method=”filterNode”。

但是此功能在input输入框每次输入一个字符就会立即过滤整个树形结构,导致需要过滤的字符还没有输入完毕,el-tree已经过滤了很多遍,造成卡顿的现象。

比如要在树形结构中过滤包含字符为“Test”的节点,输入T后el-tree就会立即过滤包含T的数据,输入e后第二次过滤包含Te的数据,输入Tes后第三次过滤包含Tes的数据,输入完Test后是第四次过滤。

为此,需要在input输入过滤的同时,在watch内增加延时功能。

<div class="treeheight" style="float:left;overflow:auto;width:30%;border:1px solid">
          <el-input :placeholder="this.$t('SQLTreemanage.filterboxdefault')" v-model="filterText"></el-input>
            <el-tree
               :props="props1"
               :load="loadNode1"
               @node-click="handlenodeclick"
               :lazy="true"
               :filter-node-method="filterNode"
               :render-content="renderContent"
               ref="tree2"
               :expand-on-click-node="false"
               >
            </el-tree>
        </div>
  const debounce = (function () {
    let timer = 0
    return function (func, delay) {
      clearTimeout(timer)
      timer = setTimeout(func, delay)
    }
  })()
  export default {
    data () {
      filterText: ''
    }
  }
      watch: {
      filterText (val) {
        debounce(() => {
          this.$refs.tree2.filter(val)
          }, 1000);
      }

通过延时过滤的功能,在input输入字符后,可在设置的延时时间1000(1秒)后进行过滤,减少了整个el-tree过滤的次数。

总结 

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Vue3 跨域配置devServer的参数和设置方法

    Vue3 跨域配置devServer的参数和设置方法

    这篇文章主要介绍了Vue3 跨域配置devServer的参数和设置,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • vue3 elmentPlus table实现列宽可拖拽功能

    vue3 elmentPlus table实现列宽可拖拽功能

    这篇文章主要介绍了vue3 elmentPlus table实现列宽可拖拽功能,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • 在Vue项目中,防止页面被缩放和放大示例

    在Vue项目中,防止页面被缩放和放大示例

    今天小编就为大家分享一篇在Vue项目中,防止页面被缩放和放大示例,具有很好的参考 价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-10-10
  • vue:axios请求本地json路径错误问题及解决

    vue:axios请求本地json路径错误问题及解决

    这篇文章主要介绍了vue:axios请求本地json路径错误问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • vue删除html内容的标签样式实例

    vue删除html内容的标签样式实例

    今天小编就为大家分享一篇vue删除html内容的标签样式实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • vue router动态路由下让每个子路由都是独立组件的解决方案

    vue router动态路由下让每个子路由都是独立组件的解决方案

    这篇文章主要介绍了vue router动态路由下让每个子路由都是独立组件的解决方案,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2018-04-04
  • vue项目添加多页面配置的步骤详解

    vue项目添加多页面配置的步骤详解

    公司使用 vue-cli 创建的 vue项目 在初始化时并没有做多页面配置,随着需求的不断增加,发现有必要使用多页面配置。这篇文章主要介绍了vue项目添加多页面配置,需要的朋友可以参考下
    2019-05-05
  • vue 3.0 使用ref获取dom元素的示例

    vue 3.0 使用ref获取dom元素的示例

    这篇文章主要介绍了vue 3.0 使用ref获取dom元素,包括vue2.x获取dom和vue3.0获取单个dom,通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • vue 项目打包时样式及背景图片路径找不到的解决方式

    vue 项目打包时样式及背景图片路径找不到的解决方式

    今天小编就为大家分享一篇vue 项目打包时样式及背景图片路径找不到的解决方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • vue 粒子特效的示例代码

    vue 粒子特效的示例代码

    本篇文章主要介绍了vue 粒子特效的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09

最新评论