如何做递归树数组函数?

How to do recursive tree array function?

我有一个无限深的文件夹树状数组。每个文件夹都有一个“hasPermission”布尔值。我想要实现的是,当父文件夹(可以位于树中的任何位置)的“hasPermission”发生变化时,它的所有子文件夹“hasPermission”也会发生变化 - 当然,祖父文件夹“hasPermission”不会改变。

例如,在下面的文件夹树中。如果 folderId: '2.1' 更改权限, folderId: '3.1' 也会更改;其他的将保持不变。

const example = [
  {
    folderId: '1',
    hasPermission: false,
    children: [
      {
        folderId: '2.1',
        hasPermission: false,
        children: [
          {
            folderId: '3.1',
            hasPermission: false,
            children: [],
          },
        ],
      },
      {
        folderId: '2.2',
        hasPermission: false,
        children: [],
      },
    ],
  },
];

此函数递归地更改“hasPermission”。

  const changeChildrenPermission = (
    folders
  ) => {
    return folders.map(
      ({ id, children, hasPermission }) => ({
        id,
        hasPermission: (hasPermission === false && true) || false,
        children: changeChildrenPermission(children),
      })
    );
  };

这是我目前所拥有的,我正在尝试查找 selectedId 的树,如果它 匹配,然后调用“changeChildrenPermission”函数。

  const setPermissionChange = (
    folders,
    selectedId
  ) => {
    const a = folders.map((folder) => {
      if (folder.id === selectedId) {
       return {
          id: folder.folderId,
          hasPermission: (hasPermission === false && true) || false,
          children: changeChildrenPermission(folder.children),
        };
    });
  };

不知道之后该做什么。

// visitFolders: Walks the folder tree recursively and calls visitFolder for every folder.
// - If visitFolder returns true for a folder, the walk stops immediately.
// - If you want to visit all folders, visitFolder should return false.
//   (Returning false can be omitted, because the default return value of functions is undefined, which is falsy.)
const visitFolders = (folders, visitFolder) => {
  for (let folder of folders) {
    if (visitFolder(folder) || visitFolders(folder.children, visitFolder)) {
      return true;
    }
  }
  return false;
};

const findFolderById = (folders, id) => {
  let folderWithId = null;
  visitFolders(folders, folder => {
    if (folder.id === id) {
      folderWithId = folder;
      return true;
    }
    return false;
  });
  return folderWithId;
};

const setFolderPermission = (folder, hasPermission) => {
  visitFolders([folder], folder => {
    folder.hasPermission = hasPermission;
    return false;
  });
};

const folders = [
  {
    id: "1",
    hasPermission: true,
    children: [
      {
        id: "1.1",
        hasPermission: true,
        children: []
      },
      {
        id: "1.2",
        hasPermission: true,
        children: [
          {
            id: "1.2.1",
            hasPermission: true,
            children: []
          },
          {
            id: "1.2.2",
            hasPermission: true,
            children: []
          }
        ]
      },
      {
        id: "1.3",
        hasPermission: true,
        children: []
      },
      {
        id: "1.4",
        hasPermission: true,
        children: []
      }
    ]
  },
  {
    id: "2",
    hasPermission: true,
    children: [
      {
        id: "2.1",
        hasPermission: true,
        children: []
      },
      {
        id: "2.2",
        hasPermission: true,
        children: []
      }
    ]
  }
];

const folder = findFolderById(folders, "1.2");
if (folder !== null) {
  setFolderPermission(folder, false);
}
visitFolders(folders, folder => {
  console.log(folder.id, folder.hasPermission);
  return false;
});