递归地找到一个节点并递归地改变它的访问
Recursively find a node and recursively change it's access
我有这个树数据:
type DataType = {
id: string;
access: 'view' | 'none';
isDisabled: boolean;
children: DataType[];
};
export const Data: DataType = {
id: '1',
access: 'view',
isDisabled: false,
children: [
{
id: '2',
access: 'view',
isDisabled: false,
children: [
{
id: '3',
access: 'view',
isDisabled: false,
children: [],
},
],
},
{
id: '4',
access: 'view',
isDisabled: false,
children: [],
},
{
id: '5',
access: 'view',
isDisabled: false,
children: [],
},
],
};
我想做的是当节点的访问权限发生变化时,isDisabled 布尔值将根据以下规则发生变化:
access为'view'时isDisabled为false,access为'none'时isDisabled为false,当前节点isDisabled为false,子节点isDisabled为true
我有这些功能:(没有像我希望的那样工作)
// this will find the node
const find = (
data: DataType,
selectedId: string,
selectedAccess: 'view' | 'none'
) => {
if (selectedId && selectedAccess) {
if (data.id === selectedId) {
data = changeAccess(data, selectedId, selectedAccess);
} else {
data.children.forEach((child) => find(child, selectedId, selectedAccess));
}
}
};
// this will change the access and isDisabled
const changeAccess = (
data: DataType,
selectedId: string,
selectedAccess: 'view' | 'none'
): DataType => ({
id: data.id,
access: selectedAccess,
isDisabled:
data.id !== selectedId && selectedAccess !== 'view' ? true : false, // condition to toggle the isDisabled
children: data.children?.map((child) =>
changeAccess(child, selectedId, selectedAccess)
),
});
所以如果我调用查找函数:
find(Data, '2', 'none');
结果将是:
const DataAfter: DataType = {
id: '1',
access: 'view',
isDisabled: false,
children: [
{
id: '2',
access: 'none', // changed from 'view' to 'none'
isDisabled: false, // remain false
children: [
{
id: '3',
access: 'none', // changed from 'view' to 'none'
isDisabled: true, // changed from false to true
children: [],
},
],
},
{
id: '4',
access: 'view',
isDisabled: false,
children: [
{
id: '5',
access: 'view',
isDisabled: false,
children: [],
},
],
},
],
};
如果我再次调用查找:
find(Data, '4', 'none');
结果将是:(注意之前的调用改变了数组并在此处反映了 id 2 和 3)
const DataAfter2: DataType = {
id: '1',
access: 'view',
isDisabled: false,
children: [
{ // id 2 & 3 remains changed from the pervious call.
id: '2',
access: 'none',
isDisabled: false,
children: [
{
id: '3',
access: 'none',
isDisabled: true,
children: [],
},
],
},
{
id: '4',
access: 'none', // changed from 'view' to 'none'
isDisabled: false, // remain false
children: [
{
id: '5',
access: 'none', // changed from 'view' to 'none'
isDisabled: true, // changed from false to true
children: [],
},
],
},
],
};
如果我调用查找:
find(Data, '1', 'none');
所有访问权限都是 'none',只有 id:1 的 isDisabled 布尔值等于 false。
最后,如果我调用查找:
find(Data, '1', 'view');
所有访问权限都将更改为 'view' 并且全部禁用并设置为 false。
我的功能没有像我希望的那样工作。非常感谢任何帮助。
很抱歉,如果您看到了类似的问题,我对递归和树数据还很陌生,想以不同的方式练习使用它。
这一行:
data = changeAccess(data, selectedId, selectedAccess)
将在 data
变量中获取一个新对象,但这并没有改变原始 data
...这是一个重新分配,丢弃了之前 data
的引用有,并且(因为 JavaScript 没有按引用调用)调用者将看不到新对象。
因为你想改变给定的数据结构,你不应该 changeAccess
return 一个新对象。它应该改变它:
const find = (
data: DataType,
selectedId: string,
selectedAccess: 'view' | 'none'
) => {
if (selectedId && selectedAccess) {
if (data.id === selectedId) {
changeAccess(data, selectedId, selectedAccess); // No return value
} else {
data.children.forEach((child) => find(child, selectedId, selectedAccess));
}
}
};
const changeAccess = (
data: DataType,
selectedId: string,
selectedAccess: 'view' | 'none'
) => Object.assign(data, { // Mutate `data`
access: selectedAccess,
isDisabled:
data.id !== selectedId && selectedAccess !== 'view', // already boolean
children: data.children?.map((child) =>
changeAccess(child, selectedId, selectedAccess)
),
});
我有这个树数据:
type DataType = {
id: string;
access: 'view' | 'none';
isDisabled: boolean;
children: DataType[];
};
export const Data: DataType = {
id: '1',
access: 'view',
isDisabled: false,
children: [
{
id: '2',
access: 'view',
isDisabled: false,
children: [
{
id: '3',
access: 'view',
isDisabled: false,
children: [],
},
],
},
{
id: '4',
access: 'view',
isDisabled: false,
children: [],
},
{
id: '5',
access: 'view',
isDisabled: false,
children: [],
},
],
};
我想做的是当节点的访问权限发生变化时,isDisabled 布尔值将根据以下规则发生变化:
access为'view'时isDisabled为false,access为'none'时isDisabled为false,当前节点isDisabled为false,子节点isDisabled为true
我有这些功能:(没有像我希望的那样工作)
// this will find the node
const find = (
data: DataType,
selectedId: string,
selectedAccess: 'view' | 'none'
) => {
if (selectedId && selectedAccess) {
if (data.id === selectedId) {
data = changeAccess(data, selectedId, selectedAccess);
} else {
data.children.forEach((child) => find(child, selectedId, selectedAccess));
}
}
};
// this will change the access and isDisabled
const changeAccess = (
data: DataType,
selectedId: string,
selectedAccess: 'view' | 'none'
): DataType => ({
id: data.id,
access: selectedAccess,
isDisabled:
data.id !== selectedId && selectedAccess !== 'view' ? true : false, // condition to toggle the isDisabled
children: data.children?.map((child) =>
changeAccess(child, selectedId, selectedAccess)
),
});
所以如果我调用查找函数:
find(Data, '2', 'none');
结果将是:
const DataAfter: DataType = {
id: '1',
access: 'view',
isDisabled: false,
children: [
{
id: '2',
access: 'none', // changed from 'view' to 'none'
isDisabled: false, // remain false
children: [
{
id: '3',
access: 'none', // changed from 'view' to 'none'
isDisabled: true, // changed from false to true
children: [],
},
],
},
{
id: '4',
access: 'view',
isDisabled: false,
children: [
{
id: '5',
access: 'view',
isDisabled: false,
children: [],
},
],
},
],
};
如果我再次调用查找:
find(Data, '4', 'none');
结果将是:(注意之前的调用改变了数组并在此处反映了 id 2 和 3)
const DataAfter2: DataType = {
id: '1',
access: 'view',
isDisabled: false,
children: [
{ // id 2 & 3 remains changed from the pervious call.
id: '2',
access: 'none',
isDisabled: false,
children: [
{
id: '3',
access: 'none',
isDisabled: true,
children: [],
},
],
},
{
id: '4',
access: 'none', // changed from 'view' to 'none'
isDisabled: false, // remain false
children: [
{
id: '5',
access: 'none', // changed from 'view' to 'none'
isDisabled: true, // changed from false to true
children: [],
},
],
},
],
};
如果我调用查找:
find(Data, '1', 'none');
所有访问权限都是 'none',只有 id:1 的 isDisabled 布尔值等于 false。
最后,如果我调用查找:
find(Data, '1', 'view');
所有访问权限都将更改为 'view' 并且全部禁用并设置为 false。
我的功能没有像我希望的那样工作。非常感谢任何帮助。
很抱歉,如果您看到了类似的问题,我对递归和树数据还很陌生,想以不同的方式练习使用它。
这一行:
data = changeAccess(data, selectedId, selectedAccess)
将在 data
变量中获取一个新对象,但这并没有改变原始 data
...这是一个重新分配,丢弃了之前 data
的引用有,并且(因为 JavaScript 没有按引用调用)调用者将看不到新对象。
因为你想改变给定的数据结构,你不应该 changeAccess
return 一个新对象。它应该改变它:
const find = (
data: DataType,
selectedId: string,
selectedAccess: 'view' | 'none'
) => {
if (selectedId && selectedAccess) {
if (data.id === selectedId) {
changeAccess(data, selectedId, selectedAccess); // No return value
} else {
data.children.forEach((child) => find(child, selectedId, selectedAccess));
}
}
};
const changeAccess = (
data: DataType,
selectedId: string,
selectedAccess: 'view' | 'none'
) => Object.assign(data, { // Mutate `data`
access: selectedAccess,
isDisabled:
data.id !== selectedId && selectedAccess !== 'view', // already boolean
children: data.children?.map((child) =>
changeAccess(child, selectedId, selectedAccess)
),
});