js使用filter递归过滤树形结构数组

本文介绍了如何在前端使用Vue.js,通过后端返回的权限编码列表来过滤树形结构的菜单。当父级菜单的权限编码不在权限列表中时,其所有子级菜单都将被过滤掉。通过递归实现菜单过滤,确保用户只看到具有相应权限的菜单项。

今天遇到了这么一个问题,一个管理系统的前端使用vue,通过路由控制用户权限。由后端返回权限编码列表,前端菜单列表需要对这些权限编码进行过滤。菜单是树形结构,如果父级菜单被过滤,则该父级下所有子级菜单也被过滤。由于是树形结构,肯定要用到递归,大致代码如下:

 

// 菜单列表
const menuList = [{
    name: '系统管理',
    code: 'system_manage',
    children: [{
        name: '用户管理',
        code: 'user_manage',
        children: [{
            name: '添加用户',
            code: 'add_user'
        }, {
            name: '编辑用户',
            code: 'edit_user'
        }, {
            name: '删除用户',
            code: 'del_user'
        }]
    }, {
        name: '角色管理',
        code: 'role_manage',
        children: [{
            name: '添加角色',
            code: 'add_role'
        }]
    }]
}, {
    name: '业务管理',
    code: 'bus_manage',
    children: [{
        name: '流程管理',
        code: 'process_manage'
    }]
}, {
    name: '订单管理',
    code: 'order_manage'
}]

// 权限列表
const myMenuCode = ['system_manage', 'user_manage', 'add_user', 'order_manage']

const filterMenu = (menuList, menuCode) => {
    return menuList.filter(item => {
        return menuCode.indexOf(item.code) > -1
    }).map(item => {
        item = Object.assign({}, item)
        if (item.children) {
            item.children = filterMenu(item.children, menuCode)
        }
        return item
    })
}

// 过滤后的菜单
const myMenu = filterMenu(menuList, myMenuCode)

console.log(myMenu)


 

<think>首先,用户的问题是:“我想在前端开发中,使用computed属性过滤树形结构中的子节点值 请问如何使用Vue.js或React中的computed属性过滤树形结构数据的子节点”。这涉及到使用Vue.js或React的computed属性来处理树形数据。 关键点是: - 在Vue.js中,computed属性用于定义基于响应式数据的计算值。 - 在React中,没有直接的computed属性,但可以使用useMemo钩子来模拟类似行为。 - 数据是树形结构,需要过滤子节点值。 我需要参考提供的引用内容: - 引用[1]:提到Vue.js的数据绑定,包括computed属性。 - 引用[2]:强调Vue.js的响应式数据绑定和v-model。 - 引用[3]和[4]:比较React和Vue.js,但没有具体细节。 - 引用[5]:展示了在React中使用useMemo来实现类似Vue的computed属性,包括set功能。 用户问题中指定了“使用computed属性过滤树形结构中的子节点值”,所以我需要提供在Vue.js和React中的实现方法。 系统级指令: - 所有行内数学表达式用$...$。 - 独立公式用$$...$$并单独成段。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾添加引用标识,如[^1]。 - 回答结构清晰,帮助用户逐步解决问题。 - 引用站内引用内容,但用户的问题是基于computed属性过滤树形数据,所以引用可能不直接相关,但可以参考。 用户上一次问题:从引用看,似乎是关于Vue.js和React的对比,但当前问题具体是过滤树形数据。 回答结构: 1. **理解问题**:解释树形结构过滤需求。 2. **在Vue.js中实现**:使用computed属性。 3. **在React中实现**:使用useMemo。 4. **代码示例**:提供简单示例。 5. **相关问题**:生成相关问题。 确保回答真实可靠:基于前端开发知识。 树形结构数据示例:假设一个对象数组,每个对象有children属性表示子节点。 过滤需求:过滤掉某些子节点,基于某个条件,比如值匹配。 在Vue.js中: - 定义一个computed属性,返回过滤后的树。 - 使用递归函数处理树形结构。 在React中: - 使用useMemo钩子,计算过滤后的树。 - 同样使用递归。 引用内容: - 引用[1]提到Vue的computed属性。 - 引用[5]提到在React中使用useMemo模拟computed。 所以,在回答中,可以引用这些。 步骤: 1. **介绍树形结构过滤**:解释树形数据,如每个节点有children。 2. **Vue.js实现**: - 使用computed属性。 - 定义一个函数,递归遍历树,过滤子节点。 - 示例代码。 3. **React实现**: - 使用useMemo。 - 类似递归函数。 - 示例代码。 4. **总结**:比较两者。 5. **生成相关问题**:基于主题。 添加引用标识:在引用站内内容时添加。 例如,在提到Vue的computed时,引用[1];在React的useMemo时,引用[5]。 数学表达式:用户问题中没有明显数学,但如果有,比如算法复杂度,用$...$格式。但这里可能不需要。 最终输出: - 回答部分。 - §§相关问题§§部分。</think>### 使用Computed属性过滤树形结构数据的子节点值(Vue.js与React实现) 在前端开发中,树形结构数据(如组织架构、菜单系统)通常以嵌套对象形式存在,每个节点包含`children`属性表示子节点。使用computed属性过滤子节点值,可以高效地实现数据响应式更新,避免手动遍历。下面我将逐步解释如何在Vue.js和React中实现这一功能,重点基于computed属性(或等效机制)进行递归过滤。核心思路是:定义一个过滤函数,递归遍历树形结构,返回满足条件的子节点集合。引用内容显示,Vue.js内置computed属性支持响应式计算[^1],而React可通过`useMemo`钩子模拟类似行为[^5]。 #### 1. **理解树形结构过滤需求** - **树形数据结构示例**:每个节点包含`id`、`value`和`children`属性。 ```javascript const treeData = [ { id: 1, value: 'A', children: [ { id: 2, value: 'B', children: [] }, { id: 3, value: 'C', children: [] } ] }, // 更多节点... ] ``` - **过滤目标**:基于条件(如`value`包含特定字符串)过滤子节点,只保留匹配节点。例如,过滤掉`value`以"B"开头的子节点。 - **为什么使用computed属性**:computed属性自动缓存计算结果,当依赖数据变化时高效更新,避免重复计算。这在树形数据处理中尤其重要,因为递归遍历可能涉及$O(n)$时间复杂度($n$为节点数)。 #### 2. **在Vue.js使用Computed属性实现** Vue.js的computed属性是响应式的,适合处理树形数据过滤。通过定义一个递归函数,在computed属性中调用它。Vue.js的响应式系统确保当原始数据变化时,过滤结果自动更新[^1]。 - **步骤**: 1. 定义递归过滤函数:遍历每个节点,检查子节点是否匹配条件。 2. 在computed属性中调用该函数。 3. 使用`v-for`渲染过滤后的数据。 - **代码示例**: ```vue <template> <div> <!-- 渲染过滤后的树 --> <ul v-for="node in filteredTree" :key="node.id"> <li>{{ node.value }}</li> <!-- 递归渲染子节点 --> <ul v-if="node.children.length > 0"> <li v-for="child in node.children" :key="child.id">{{ child.value }}</li> </ul> </ul> </div> </template> <script> export default { data() { return { treeData: [ /* 树形数据,如上示例 */ ], filterValue: 'B' // 过滤条件,例如只保留value包含'B'的子节点 }; }, computed: { filteredTree() { // 定义递归过滤函数 const filterChildren = (nodes) => { return nodes.map(node => { // 复制节点以避免修改原始数据 const newNode = { ...node }; // 递归过滤子节点 if (newNode.children && newNode.children.length > 0) { newNode.children = filterChildren(newNode.children).filter(child => child.value.includes(this.filterValue) // 过滤条件:子节点value包含filterValue ); } return newNode; }); }; return filterChildren(this.treeData); } } }; </script> ``` - **说明**: - `filteredTree`是computed属性,当`treeData`或`filterValue`变化时自动更新。 - 递归函数`filterChildren`处理嵌套结构,使用`filter`方法过滤子节点。 - 时间复杂度约为$O(n)$,Vue的响应式优化确保高效执行[^1]。 #### 3. **在React中使用useMemo模拟Computed属性** React没有内置computed属性,但可通过`useMemo`钩子实现类似效果。`useMemo`缓存计算结果,当依赖项变化时重新计算,相当于computed的get功能[^5]。结合递归函数,处理树形数据。 - **步骤**: 1. 使用`useState`管理数据和过滤条件。 2. 定义递归过滤函数。 3. 在`useMemo`中调用函数,返回过滤结果。 4. 使用JSX渲染。 - **代码示例**: ```jsx import React, { useState, useMemo } from 'react'; function TreeFilter() { const [treeData, setTreeData] = useState([ /* 树形数据,同上 */ ]); const [filterValue, setFilterValue] = useState('B'); // 过滤条件 // 使用useMemo模拟computed属性 const filteredTree = useMemo(() => { const filterChildren = (nodes) => { return nodes.map(node => { const newNode = { ...node }; if (newNode.children && newNode.children.length > 0) { newNode.children = filterChildren(newNode.children).filter(child => child.value.includes(filterValue) // 过滤条件 ); } return newNode; }); }; return filterChildren(treeData); }, [treeData, filterValue]); // 依赖项:当treeData或filterValue变化时重新计算 return ( <div> <input type="text" value={filterValue} onChange={(e) => setFilterValue(e.target.value)} placeholder="输入过滤值" /> <ul> {filteredTree.map(node => ( <li key={node.id}> {node.value} {node.children.length > 0 && ( <ul> {node.children.map(child => ( <li key={child.id}>{child.value}</li> ))} </ul> )} </li> ))} </ul> </div> ); } export default TreeFilter; ``` - **说明**: - `useMemo`缓存计算结果,依赖项`[treeData, filterValue]`确保数据变化时更新。 - 递归逻辑与Vue类似,但React需手动管理状态更新。 - 性能:`useMemo`减少不必要的渲染,优化树形数据处理[^5]。 #### 4. **关键注意事项** - **性能优化**:树形数据递归可能引发性能问题(深度大时)。建议: - 添加终止条件(如最大深度)。 - 在Vue中,使用`computed`缓存;在React中,依赖项精确控制`useMemo`重算。 - **框架差异**: - Vue.js更简单:computed内置响应式,代码更简洁[^1]。 - React更灵活:`useMemo`可结合其他钩子,但需手动处理状态[^5]。 - **错误处理**:确保过滤条件不破坏树结构(如空children处理)。 #### 5. **总结** - **Vue.js**:利用computed属性定义递归过滤函数,实现响应式更新。 - **React**:使用`useMemo`钩子模拟computed,结合递归函数。 - 通用技巧:递归算法是核心,时间复杂度为$O(n)$,适用于中小型树。测试时,确保过滤条件覆盖边界情况(如空树或叶子节点)。 通过以上方法,您可以高效过滤树形结构中的子节点值,提升前端数据处理能力。如需进一步优化(如虚拟滚动处理大型树),可参考框架文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值