过滤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,适合需要精简输出的情况。
相关推荐
apcipot_rain3 小时前
【应用密码学】实验五 公钥密码2——ECC
前端·数据库·python
油丶酸萝卜别吃3 小时前
OpenLayers 精确经过三个点的曲线绘制
javascript
ShallowLin3 小时前
vue3学习——组合式 API:生命周期钩子
前端·javascript·vue.js
Nejosi_念旧3 小时前
Vue API 、element-plus自动导入插件
前端·javascript·vue.js
互联网搬砖老肖3 小时前
Web 架构之攻击应急方案
前端·架构
pixle04 小时前
Vue3 Echarts 3D饼图(3D环形图)实现讲解附带源码
前端·3d·echarts
麻芝汤圆4 小时前
MapReduce 入门实战:WordCount 程序
大数据·前端·javascript·ajax·spark·mapreduce
juruiyuan1116 小时前
FFmpeg3.4 libavcodec协议框架增加新的decode协议
前端
Peter 谭6 小时前
React Hooks 实现原理深度解析:从基础到源码级理解
前端·javascript·react.js·前端框架·ecmascript
周胡杰7 小时前
鸿蒙接入flutter环境变量配置windows-命令行或者手动配置-到项目的创建-运行demo项目
javascript·windows·flutter·华为·harmonyos·鸿蒙·鸿蒙系统