前端遇到过的坑13(重点:树结构的搜索展示 及 全选功能)

68 阅读2分钟

嵌套数组里匹配到关键字的叶子节点保留树结构筛出来

  • 测arr的对象子节点里name属性里是否含有关键字,筛出来分支组成新数组
  • 设计思想:child有值就保留自己,查儿子,儿子自己匹配不到就查孙子,层层保留,直到最后一层若dot啥都没,就舍弃这一枝
    rebuildTree(value, arr) {
      if (!arr) {
        return []
      }
      let newarr = []
      arr.forEach((el) => {
        if (el.name.includes(value)) {
          const dot = this.rebuildTree(value, el.child)
          // 若筛选项匹配到,但它的子节点没有被匹配到的,不放到最终数组里(只筛选匹配叶子节点) 
          // 若想中间节点也可以被筛选,去掉该判断条件即可
          if (dot.length === 0 && el.child.length === 0) {
            const obj = {
              ...el,
              child: dot,
            }
            newarr.push(obj)
          }
        } else {
          if (el.child && el.child.length > 0) {
            const dot = this.rebuildTree(value, el.child)
            const obj = {
              ...el,
              child: dot,
            }
            if (dot && dot.length > 0) {
              newarr.push(obj)
            }
          }
        }
      })
      return newarr
    },
    
--------实验数据--------
   let arr =  [
            {
              id: '1',
              name: '客户等级',
              child: [
                {
                  id: '14',
                  name: '一般',
                  child: [],
                },
                {
                  id: '15',
                  name: '重要',
                  child: [],
                },
                {
                  id: '16',
                  name: '核心',
                  child: [],
                },
              ],
            },
            {
              id: '3',
              name: '交易类型',
              child: [
                {
                  id: '32',
                  name: '小于1万元',
                  child: [],
                },
              ],
            }
          ]

列表由筛选条件控制时的全选按钮

         <el-checkbox v-model="selAll"
                       class="sel-all"
                       size="medium ">全选</el-checkbox>
                       
  computed: {
    // 全选选中/取消 都是针对当前可见列表进行操作,之前选中的且不在当前筛选后的列表中的标签不受影响
    selAll: {
      get() {
        if (this.showTagsList?.length > 0) {
          return this.showTagsList.every((el) => {
            return this.selArry.some((el1) => el1.id === el.id)
          })
        } else {
          return false
        }
      },
      set(val) {
        let finalList
        const overlapList = this.showTagsList.filter((el) =>
          this.selArry.some((el1) => el1.id === el.id)
        )

        if (val) {
          // selArry没有 showTagsList有 让selArry有
          let gapList = this.showTagsList.filter((el) => {
            if (overlapList.length > 0) {
              return overlapList.some((el1) => el1.id !== el.id)
            } else {
              // overlapList为空时,只要filter启动,都采用
              return true
            }
          })
          finalList = [...this.selArry, ...gapList]
        } else {
          // selArry有 showTagsList也有 从selArry里剔除
          // overlapList为空数组时,说明selArry里没有要清理的东西,[].some会返回false,不需要对空数组的some方法做返回值处理
          finalList = this.selArry.filter((el) =>
            overlapList.every((el1) => el1.id !== el.id)
          )
        }
        this.$emit('selArrayChange', finalList)
      },
    },

把叶子节点组成数组

function circlePick(inArry, outArry) {
  inArry.forEach((el) => {
    if (el.child?.length > 0) {
      circlePick(el.child, outArry);
    } else {
      outArry.push(el);
    }
  });
}

export function flatTreeArray(array) {
  let flatArray = [];
  circlePick(array, flatArray);
  return flatArray;
}