过滤tree数据中某些数据

在处理树形数据时,如果需要过滤掉 id 为某些特定值的项(包括这些项的子节点),可以通过递归遍历树形数据来实现。假设树形数据结构中每个节点的子节点字段为 children,以下是几种实现方法:


方法 1:递归过滤

使用递归函数遍历树,检查每个节点的 id,如果匹配需要过滤的值,则移除该节点及其子节点。

javascript 复制代码
// 假设树形数据
const treeData = [
  { id: 1, name: '节点1', children: [{ id: 11, name: '节点1-1' }] },
  { id: 2, name: '节点2', children: [{ id: 21, name: '节点2-1' }] },
  { id: 3, name: '节点3' }
];

// 需要过滤的 id 数组
const filterIds = [2, 11];

// 递归过滤函数
function filterTree(data, filterIds) {
  return data.filter(node => {
    // 如果当前节点的 id 在过滤列表中,直接排除
    if (filterIds.includes(node.id)) {
      return false;
    }
    // 如果有子节点,递归过滤子节点
    if (node.children && node.children.length > 0) {
      node.children = filterTree(node.children, filterIds);
    }
    return true;
  });
}

// 执行过滤
const filteredTree = filterTree(treeData, filterIds);
console.log(JSON.stringify(filteredTree, null, 2));

输出结果

json 复制代码
[
  {
    "id": 1,
    "name": "节点1",
    "children": []
  },
  {
    "id": 3,
    "name": "节点3"
  }
]

说明

  • filterIds 包含需要移除的 id(例如 [2, 11])。
  • filterTree 函数递归遍历树,遇到匹配 id 的节点直接返回 false(移除),并对子节点递归处理。

方法 2:深拷贝后过滤(避免修改原数据)

如果不希望修改原始数据,可以先深拷贝一份数据再进行过滤。

javascript 复制代码
function deepClone(obj) {
  return JSON.parse(JSON.stringify(obj));
}

function filterTree(data, filterIds) {
  const clonedData = deepClone(data);
  return clonedData.filter(node => {
    if (filterIds.includes(node.id)) {
      return false;
    }
    if (node.children && node.children.length > 0) {
      node.children = filterTree(node.children, filterIds);
    }
    return true;
  });
}

const treeData = [
  { id: 1, name: '节点1', children: [{ id: 11, name: '节点1-1' }] },
  { id: 2, name: '节点2', children: [{ id: 21, name: '节点2-1' }] },
  { id: 3, name: '节点3' }
];
const filterIds = [2, 11];

const filteredTree = filterTree(treeData, filterIds);
console.log(JSON.stringify(filteredTree, null, 2));
console.log('原始数据未改变:', JSON.stringify(treeData, null, 2));

优点

  • 原数据保持不变,适合需要保留原始数据的场景。

方法 3:Vue 3 响应式数据处理

如果在 Vue 3 中使用(如 refreactive),需要确保响应式数据正确更新。

vue 复制代码
<template>
  <el-tree :data="filteredTreeData" :props="treeProps" node-key="id" />
</template>

<script setup>
import { ref, onMounted } from 'vue';

// 树形数据
const treeData = ref([
  { id: 1, name: '节点1', children: [{ id: 11, name: '节点1-1' }] },
  { id: 2, name: '节点2', children: [{ id: 21, name: '节点2-1' }] },
  { id: 3, name: '节点3' }
]);

// 过滤后的数据
const filteredTreeData = ref([]);

// 树节点配置
const treeProps = {
  label: 'name',
  children: 'children'
};

// 需要过滤的 id
const filterIds = [2, 11];

// 过滤函数
function filterTree(data, filterIds) {
  return data.filter(node => {
    if (filterIds.includes(node.id)) {
      return false;
    }
    if (node.children && node.children.length > 0) {
      node.children = filterTree(node.children, filterIds);
    }
    return true;
  });
}

// 初始化时过滤数据
onMounted(() => {
  filteredTreeData.value = filterTree(treeData.value, filterIds);
});
</script>

说明

  • 使用 ref 管理树形数据,确保过滤后赋值给 filteredTreeData
  • el-tree 使用过滤后的数据渲染。

方法 4:处理空 children 数组(可选优化)

在上述方法中,过滤后可能出现 children: [] 的空数组。如果不需要保留空数组,可以在递归时清理。

javascript 复制代码
function filterTree(data, filterIds) {
  return data
    .filter(node => !filterIds.includes(node.id))
    .map(node => {
      if (node.children && node.children.length > 0) {
        node.children = filterTree(node.children, filterIds);
        // 如果子节点过滤后为空,删除 children 属性
        if (node.children.length === 0) {
          delete node.children;
        }
      }
      return node;
    });
}

const treeData = [
  { id: 1, name: '节点1', children: [{ id: 11, name: '节点1-1' }] },
  { id: 2, name: '节点2', children: [{ id: 21, name: '节点2-1' }] },
  { id: 3, name: '节点3' }
];
const filterIds = [2, 11];

const filteredTree = filterTree(treeData, filterIds);
console.log(JSON.stringify(filteredTree, null, 2));

输出结果

json 复制代码
[
  {
    "id": 1,
    "name": "节点1"
  },
  {
    "id": 3,
    "name": "节点3"
  }
]

优点

  • 移除空 children,数据更简洁。

注意事项

  1. 数据结构一致性

    • 确保树形数据中每个节点都有 idchildren(即使为空数组)。
    • 如果字段名不同(如子节点字段不是 children),需调整代码中的字段名。
  2. 性能考虑

    • 对于大规模树形数据,递归可能有性能开销,但通常中小型数据无明显影响。
  3. 动态过滤

    • 如果 filterIds 是动态变化的(例如用户选择),可以在 Vue 中将其设为响应式变量,并在变化时重新调用 filterTree

总结

  • 推荐方法:方法 1(递归过滤)简单直接,适用于大多数场景。
  • Vue 3 场景 :使用方法 3,结合 refreactive
  • 数据清洁 :方法 4 可移除空 children,适合需要精简输出的情况。
相关推荐
hikktn13 分钟前
【开源宝藏】30天学会CSS - DAY9 第九课 牛顿摆动量守恒动画
前端·css·开源
悦涵仙子1 小时前
NG-ZORRO中tree组件的getCheckedNodeList怎么使用
javascript·ecmascript·angular.js
申朝先生1 小时前
面试的时候问到了HTML5的新特性有哪些
前端·信息可视化·html5
在下千玦2 小时前
#前端js发异步请求的几种方式
开发语言·前端·javascript
知否技术2 小时前
面试官最爱问的Vue3响应式原理:我给你讲明白了!
前端·vue.js
Angelyb2 小时前
前端Vue
开发语言·javascript·ecmascript
小周同学:2 小时前
vue将页面导出成word
前端·vue.js·word
阿杰在学习3 小时前
基于OpenGL ES实现的Android人体热力图可视化库
android·前端·opengl
xfq3 小时前
[ai] cline使用总结(包括mcp)
前端·后端·ai编程
weiran19993 小时前
手把手的建站思路和dev-ops方案
前端·后端·架构