如何递归遍历树形json数据,获取所有的ID值

问题描述

使用element-ui组件开发一个文件管理系统,其中用到了树形控件,后台返回的数据是树形结构数据,前端渲染时实现树形组件默认勾选,通过绑定node-key="id" ,:default-checked-keys来实现,数据中的ID要怎么一次性获取

问题出现的环境背景及自己尝试过哪些方法

自己写了用FOR循环实现,目前只有两级节点,写了两次循环,以后可能会有更多子节点,会显得代码过于冗长,有没有什么办法遍历所有子节点,获取所有id到数组里

相关代码

后台数据

{
"id": 1,
"state": 0,
"createTime": "2019-10-25T06:17:47.000+0000",
"updateTime": "2019-10-25T06:17:47.000+0000",
"pid": 0,
"name": "用户管理",
"code": "USER",
"type": 1,
"path": "/user",
"icon": "user",
"orders": 0,
"hasPermission": true,
"subPermission": [{
    "id": 2,
    "state": 0,
    "createTime": "2019-11-07T08:24:30.000+0000",
    "updateTime": "2019-11-07T08:24:31.000+0000",
    "pid": 1,
    "name": "用户列表",
    "code": "USER:LIST",
    "type": 2,
    "path": "/user-list",
    "icon": "user-list",
    "orders": 0,
    "hasPermission": true,
    "subPermission": []
}, {
    "id": 24,
    "state": 0,
    "createTime": "2019-11-29T07:28:03.000+0000",
    "updateTime": "2019-11-29T07:28:03.000+0000",
    "pid": 1,
    "name": "仪表盘",
    "code": "DASHBOARD",
    "type": 1,
    "path": "/dashboard",
    "icon": "dashboard",
    "orders": 100,
    "hasPermission": false,
    "subPermission": []
}]
}, {
"id": 3,
"state": 0,
"createTime": "2019-11-07T08:26:58.000+0000",
"updateTime": "2019-11-07T08:27:00.000+0000",
"pid": 0,
"name": "文件管理",
"code": "FILE",
"type": 1,
"path": "/file",
"icon": "file",
"orders": 0,
"hasPermission": false,
"subPermission": [{
    "id": 4,
    "state": 0,
    "createTime": "2019-11-07T08:27:42.000+0000",
    "updateTime": "2019-11-07T08:27:43.000+0000",
    "pid": 3,
    "name": "文件列表",
    "code": "FILE:LIST",
    "type": 2,
    "path": "/file-list",
    "icon": "file-list",
    "orders": 0,
    "hasPermission": false,
    "subPermission": []
}]
}, {
"id": 5,
"state": 0,
"createTime": "2019-11-07T08:28:30.000+0000",
"updateTime": "2019-11-07T08:28:33.000+0000",
"pid": 0,
"name": "权限管理",
"code": "AUTH",
"type": 1,
"path": "/auth",
"icon": "auth",
"orders": 0,
"hasPermission": false,
"subPermission": [{
    "id": 6,
    "state": 0,
    "createTime": "2019-11-07T08:29:47.000+0000",
    "updateTime": "2019-11-07T08:29:48.000+0000",
    "pid": 5,
    "name": "员工列表",
    "code": "AUTH:STAFF:LIST",
    "type": 2,
    "path": "/staff-list",
    "icon": "staff-list",
    "orders": 0,
    "hasPermission": true,
    "subPermission": []
}, {
    "id": 7,
    "state": 0,
    "createTime": "2019-11-07T08:30:57.000+0000",
    "updateTime": "2019-11-07T08:30:59.000+0000",
    "pid": 5,
    "name": "角色列表",
    "code": "AUTH:ROLE:LIST",
    "type": 2,
    "path": "/role-list",
    "icon": "role-list",
    "orders": 1,
    "hasPermission": true,
    "subPermission": []
}, {
    "id": 8,
    "state": 0,
    "createTime": "2019-11-07T08:32:00.000+0000",
    "updateTime": "2019-11-07T08:32:01.000+0000",
    "pid": 5,
    "name": "权限列表",
    "code": "AUTH:PERMISSION:LIST",
    "type": 2,
    "path": "/permission-list",
    "icon": "permission-list",
    "orders": 2,
    "hasPermission": false,
    "subPermission": []
}]
}, {
"id": 22,
"state": 0,
"createTime": "2019-11-08T02:54:44.000+0000",
"updateTime": "2019-11-08T02:54:44.000+0000",
"pid": 0,
"name": "测试菜单111",
"code": "TESTQ",
"type": 1,
"path": "/testsss",
"icon": "u",
"orders": 30,
"hasPermission": false,
"subPermission": []
}

渲染

<el-tree
    ref="tree"
    :data="data"
    node-key="id"
    border
    show-checkbox
    default-expand-all
    highlight-current
    :props="{children: 'subPermission', label: 'name'}"
    :default-checked-keys="checkedKeys"
    @check-change="handleCheckChange"
  />

<template>
 <div class="roleTree">
<el-dialog title="权限查询" :visible.sync="dialogAdd.show">
  <el-tree
    ref="tree"
    :data="data"
    node-key="id"
    border
    show-checkbox
    default-expand-all
    highlight-current
    :props="{children: 'subPermission', label: 'name'}"
    :default-checked-keys="checkedKeys"
    @check-change="handleCheckChange"
  />
  <div slot="footer" class="dialog-footer">
    <el-button @click="dialogAdd.show = false">取 消</el-button>
    <el-button type="primary" @click="dialogFormAdd">确 定</el-button>
  </div>
</el-dialog>
 </div>
</template>

<script>
export default {
 name: 'RoleTree',
 components: {
 },
inject: ['reload'],
props: {
// eslint-disable-next-line vue/require-default-prop
dialogAdd: Object,
object: Object
 },
 data() {
return {
  roleId: 0,
  data: [],
  checkedKeys: [],
  addIds: [],
  delIds: []
}
 },
 created() {
console.log(this.dialogAdd.id)
if (this.dialogAdd.id != null && this.dialogAdd.id !== 0) {
  this.roleId = this.dialogAdd.id
  this.$store.dispatch('role/roleTree', this.dialogAdd.id).then(() => { // 获取接口详细数据
    console.log('1111111' + JSON.stringify(this.$store.state.role.getTree))
    this.data = this.$store.state.role.getTree // 数据赋值给data: []
    this.checkedKeys = []
    for (let i = 0; i < this.data.length; i++) {
      console.log('1111111' + JSON.stringify(this.data[i]))
      if (this.data[i].hasPermission === true) {
        this.checkedKeys.push(this.data[i].id)
      }
      if (this.data[i].subPermission !== undefined && this.data[i].subPermission.length !== 0) {
        for (let j = 0; j < this.data[i].subPermission.length; j++) {
          console.log('2222' + JSON.stringify(this.data[i].subPermission[j]))
          if (this.data[i].subPermission[j].hasPermission === true) {
            this.checkedKeys.push(this.data[i].subPermission[j].id)
          }
        }
      } // 递归
    }
    console.log('1111111' + JSON.stringify(this.checkedKeys))
  })
}
},

把代码重新贴了一下。想要实现的就是能不能帮我用递归的方式获取到所有的id放在checkedKeys里,放在created使其打开弹窗页自动渲染。
本人菜鸟,刚接触vue这个框架,很多都不懂哈,谢谢了
__
说明一下后台返回的数据,hasPermission代表是否默认勾选,需求是当hasPermission:true时获取当前id。
遍历所有节点获取所有当hasPermission为true时的id,哭求支援~~

阅读 10.2k
4 个回答
function collectId(arr, ids = []) {
  arr.forEach(({ id, subPermission }) => {
    if (id) {
      ids.push(id);
    }
    if (subPermission) {
      collectId(subPermission, ids);
    }
  });
  return ids;
}

不确定我的理解是不是跟你的想法一样,如果有问题可以继续在提问

试着写了一个,发现和第一个回答一样,就不往上贴了。。。

给一个奇淫巧技

function collectId(obj, id='id', checked='hasPermission') {
  let ids = [], checks = [];
  JSON.stringify(obj, (k, v) => {
    if (k === id) { ids.push(v) }
    if (k === checked) { checks.push(v) }
    return v
  })
  return ids.filter((id, i) => checks[i]);
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏