【问题标题】:Flatten routes tree展平路线树
【发布时间】:2019-03-13 16:05:58
【问题描述】:

我正在尝试找到一种方法来展平带有路由(vanilla js)和子路由的数组,以便我得到一个包含同一级别对象的数组,但使用它们的 namepath属性基于他们的“级别”。

例如,我希望 namedashboard.settings.user....... 类似,path 也可以将路径连接到“有效”路径。

我一直在尝试使用递归函数,但不知道如何跟踪关卡..

更新:

var routesConfig = [
    {
        name: 'dashboard',
        path: '/dashboard',
        children: [
            {
                name: 'settings',
                path: '/settings',
                children: [
                    {
                        name: 'user',
                        path: '/user'
                    },
                    {
                        name: 'email',
                        path: '/email',
                        children: [
                            {
                                name: 'template',
                                path: '/template',
                                children: [
                                    {
                                        name: 'error',
                                        path: '/error'
                                    },
                                    {
                                        name: 'success',
                                        path: '/success'
                                    }
                                ],
                                name: 'lists',
                                path: '/lists',
                                children: [
                                    {
                                        name: 'signup',
                                        path: '/signup'
                                    },
                                    {
                                        name: 'newsletter',
                                        path: '/newsletter'
                                    }
                                ]
                            },
                            {
                                name: 'sender',
                                path: '/sender'
                            }
                        ]
                    }
                ]
            },
            {
                name: 'contact',
                path: '/contact',
                children: [
                    {
                        name: 'person',
                        path: '/person',
                        children: [
                            {
                                name: 'john',
                                path: '/john'
                            },
                            {
                                name: 'jane',
                                path: '/jane'
                            }
                        ]
                    }
                ]
            }
        ]
    },
]

flattenRoutes();

function flattenRoutes(){
    let routes = [];

    routesConfig.map(route => {
        const {name, path, children} = route;
        routes.push({name, path});

        if(children && children.length){
            iterateRouteChildren(route, routes, 1, []);
        }
    });

    console.log("routes", routes);
}

function iterateRouteChildren(parent, routes, depth, tree){
    for(let i = 0; i < parent.children.length; i++){
        let childRoute = parent.children[i];

        let name = childRoute.name;
        let path = childRoute.path;

        if(depth === 1){
            tree = [];
        }else{
            tree.push(childRoute.name)

        }

        routes.push({name, path, tree: tree.filter(Boolean).join('.')});

        if(childRoute.children && childRoute.children.length){
            iterateRouteChildren(childRoute, routes, depth + 1, tree);
        }

    }
}

更新 2:

基于 Nina 解决方案,我要求保留原始对象/值的方法,但 namepath 被重写为它们的“新”值,例如路由“电子邮件”应该有它的 @987654333 @ 阅读:dashboard.settings.email,它是 path 重写为:/dashboard/settings/email 所以对每个对象进行变异,并保持不变的属性(但仍将其保持为平面数组,因此没有嵌套的子数组)。

更新 3:

试图澄清。我的嵌套 routesConfig 将包含具有“名称”、“路径”、“其他属性”和可能“孩子”等属性的对象。

我想把整棵树弄平,所以一切都在同一水平上,但所有孩子都应该根据他们在树的深度来重写他们的“名字”和“路径”。示例:

let result = [
    {
        name: 'dashboard',
        path: '/dashboard',
        id: 'my-dashboard-id',
        someotherprop: someothervalue
        ...
    },
    {
        name: 'dashboard.settings',
        path: '/dashboard/settings',
        id: 'my-settings-id',
        someotherprop: someothervalue
        ...
    },
    {
        name: 'dashboard.settings.user',
        path: '/dashboard/settings/user',
        id: 'my-user-id',
        someotherprop: someothervalue
        ...
    },
    {
        name: 'dashboard.settings.email',
        path: '/dashboard/settings/email',
        id: 'my-email-id',
        someotherprop: someothervalue
        ...
    },
    {
        name: 'dashboard.settings.email.template',
        path: '/dashboard/settings/email/template',
        id: 'my-template-id',
        someotherprop: someothervalue
        ...
    },
    {
        name: 'dashboard.settings.email.template.error',
        path: '/dashboard/settings/email/template.error',
        id: 'my-error-id',
        someotherprop: someothervalue
        ...
    },
    .....
]

谢谢

【问题讨论】:

  • 请在问题中包含所有相关信息,而不是链接到其他网站。
  • 在这里,您的整个问题(包括任何必要的代码)必须您的问题中,而不仅仅是链接。两个原因:人们不应该去场外帮助你;和链接腐烂,使问题及其答案对未来的人们毫无用处。请将所有相关代码等(最好是minimal reproducible example放入问题中。更多:How do I ask a good question?Something in my web site or project doesn't work. Can I just paste a link to it?
  • 好的,请看我更新的答案。
  • 仅供参考,您可以将 Stack Snippets([&lt;&gt;] 工具栏按钮)用于可运行的示例。 Here's how to do one.
  • 顺便说一句,模板和列表之间有错误。你需要结束最后一个对象和一个新对象,比如}, {

标签: javascript recursion tree


【解决方案1】:

您可以通过将最后一个 namepath 移交给嵌套对象来采用迭代和递归方法。

function getFlat(array, n = '', p = '') {
    return array.reduce((r, { children = [], ...o }) => {
        var name = n + (n && '.') + o.name,
            path = p + o.path;
        return r.concat(Object.assign({}, o, { name, path }), getFlat(children, name, path));
    }, []);
}

var routes = [{ name: 'dashboard', path: '/dashboard', children: [{ name: 'settings', path: '/settings', children: [{ name: 'user', path: '/user' }, { name: 'email', path: '/email', children: [{ name: 'template', path: '/template', children: [{ name: 'error', path: '/error' }, { name: 'success', path: '/success' }] }, { name: 'lists', path: '/lists', children: [{ name: 'signup', path: '/signup' }, { name: 'newsletter', path: '/newsletter' }] }, { name: 'sender', path: '/sender' }] }] }, { name: 'contact', path: '/contact', children: [{ name: 'person', path: '/person', children: [{ name: 'john', path: '/john' }, { name: 'jane', path: '/jane' }] }] }] }],
    flat = getFlat(routes);

console.log(flat);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 真的很好。但是,项目“dashboard”的值不包括在内,或者“dashboard.settings”也不包括在内。也许我不够清楚,抱歉。
  • 啊,太好了!这看起来真的很好。我将如何重写每个对象?例如, /sender 现在应该在其属性上改为 /dashboard/settings/email/sender .. ? (与 name 属性一样,但基于其名称,用点分隔)
  • 请在问题中添加想要的结果。你喜欢改变数据,还是获取新的数组/对象?
  • 啊,对不起。它可能是任何一种方式,我想在这种情况下 mutate 可能会更好。我已经更新了这个问题,希望能很好地解释我想要实现的目标。
  • 尼娜,我注意到你更新了你的答案。我的意思是保持扁平结构,所以没有子数组,但应该保留所有其他属性,并且应该将名称和路径重写为它们的层次结构......对不起。希望你有精力再看一遍;)
猜你喜欢
  • 1970-01-01
  • 2020-07-01
  • 1970-01-01
  • 2017-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-31
  • 1970-01-01
相关资源
最近更新 更多