项目(vue+TS)背景,总共有三级菜单,二级菜单数据是已有的,三级菜单数据是根据二级菜单动态拉取渲染的,且当第二次请求时,不在重新请求,只是把上一次请求的数据拿来渲染就行了,减少了请求。

参考 element-UI-tree

按需引入

element.js
import {
  Scrollbar,
} from "element-ui";    

Vue.use(Scrollbar);

template

<el-scrollbar wrap-class="scroll-viewport-tree">
   <div class="container">
     <el-tree
       :data="treeData"
       :props="defaultProps"
       @node-click="handleNodeClick"
       :load="loadNode"
       lazy
     ></el-tree>
   </div>
 </el-scrollbar>

相关数据

private treeData: arrayData = [];
private defaultProps = {
  children: "children",
  label: "label",
  isLeaf: "leaf"
};

由本地数据生成一级节点树

private generateTreeData(): void {
  this.treeData = [];
  const firstChild: any = [];
  for (const k in this.ROLE_TYPE) {
    firstChild.push({
      label: this.ROLE_TYPE[k],
      key: k,
      children: []
    });
  }
  this.treeData = [
    { 
    	label: this.UserInfo.project_name, 
    	children: [...firstChild] 
    }
  ];
}

这里设置懒加载事件

private async loadNode(node: objectData, resolve: Function): any {
//一级默认显示
 if (node.level === 0) {
   return resolve(this.treeData);
 }
 //二级直接放回本地数据
 if (node.level === 1) {
   setTimeout(() => {
     return resolve(this.treeData[0].children);
   });
 }
 // 点击二级菜单时候异步拉取数据做渲染
 if (node.level === 2) {
   if (node.data.key) {
     try {
       let data!: arrayData;
       if (
         this.treeData[0].children[node.data.key - 1].children.length > 1
       ) {
         data = this.treeData[0].children[node.data.key - 1].children;
       } else data = await this.getAdminsByRole(node.data.key);
       return resolve(data);
     } catch (err) {
       // 捕获promise错误
       this.$message.error(err.toString());
     }
   }
 }
 if (node.level > 2) {
   return resolve([]);
 }
}

获取数据函数

private getAdminsByRole(key: string): any {
  const key1 = Number(key);
  return new Promise((resolve, reject) => {
    this.$https.userMan
      .getAllAdmin({
        data: {
          role: 2
        }
      })
      .then((res: fetchResponse) => {
        if (res.flag === 1 && res.data.results.length > 0) {
          res.data.results.forEach((item: objectData) => {
            this.treeData[0].children[key1 - 1].children.push({
              label: item.nickname,
              // leaf为true时,展开节点没有下拉符号(三角)
              leaf: true,
              children: [],
              ...item
            });
          });
          this.treeData[0].children[key1 - 1].children.shift();
          resolve(this.treeData[0].children[key1 - 1].children);
        } else reject();
      })
      .catch((err: any) => reject(err));
  });
}

最后效果:
在这里插入图片描述


自定义过滤:

页面样子
在这里插入图片描述
如果使用官方过滤:

this.refs.tree.filter(params)

eslint会报错:
在这里插入图片描述
当然不影响执行,但是这种错误会导致打包失败,当然各位看官如果有办法解决此error,欢迎留言

想要避免错误参考: vue+ts对element $refs.xxx.methods的支持

最后的搜索方法,其实就是利用nickname和id筛选子节点

private search() {
    const { nickname, id } = this.searchInfo;
    //this.$refs.tree.filter([nickname, id])
    this.treeData = deepClone(this.treeDataSource);
    this.treeData[0].children.forEach((item: objectData) => {
      // 过滤后的子节点	
      const subArr: arrayData = [];
      item.children.forEach((val: objectData) => {
        if (
          val.nickname.indexOf(nickname) !== -1 &&
          String(val.id).indexOf(id) !== -1
        ) {
          subArr.push(val);
        }
      });
      item.children = [...subArr];
    });
    this.treeData[0].children = this.treeData[0].children.filter(item => {
      return item.children.length > 0;
    });
    if (this.treeData[0].children.length === 0) {
      this.errorTips = "查询该用户失败!";
    } else {
      // 奇怪的是这个默认展开无效
      this.expandTree = true;
      this.errorTips = "";
    }
  }
Logo

前往低代码交流专区

更多推荐