从多层嵌套的 object 中搜索配对的值然后进行操作的最佳实践是什么?

2022-04-14 23:34:07 +08:00
 rv54ntjwfm3ug8

假设有数据:

let data = [
    {
        label: 'Home',
        items: [
            { label: 'Dashboard', icon: 'pi pi-fw pi-home', routerLink: ['/'] }
        ]
    },
    {
        label: 'UI Components',
        items: [
            { label: 'Form Layout', icon: 'pi pi-fw pi-id-card', routerLink: ['/uikit/formlayout'] },
            { label: 'Input', icon: 'pi pi-fw pi-check-square', routerLink: ['/uikit/input'] },
            { label: 'Float Label', icon: 'pi pi-fw pi-bookmark', routerLink: ['/uikit/floatlabel'] },
            { label: 'Invalid State', icon: 'pi pi-fw pi-exclamation-circle', routerLink: ['/uikit/invalidstate'] },
            { label: 'Button', icon: 'pi pi-fw pi-mobile', routerLink: ['/uikit/button'], class: 'rotated-icon' },
            { label: 'Table', icon: 'pi pi-fw pi-table', routerLink: ['/uikit/table'] },
        ]
    },
    {
        label: 'Blocks',
        items: [
            { label: 'List', icon: 'pi pi-fw pi-list', routerLink: ['/uikit/list'] },
            { label: 'Tree', icon: 'pi pi-fw pi-share-alt', routerLink: ['/uikit/tree'] },
            { label: 'Panel', icon: 'pi pi-fw pi-tablet', routerLink: ['/uikit/panel'] },
            
            { label: 'Google', icon: 'pi pi-fw pi-globe', url: ['https://www.google.com'], target: '_blank' },
            { label: 'Bing', icon: 'pi pi-fw pi-comment', url: ['https://www.bing.com'] },
            
            {
                label: 'More',
                items: [
                    { label: 'List', icon: 'pi pi-fw pi-list', routerLink: ['/uikit/list'] },
                    
                    { label: 'Google', icon: 'pi pi-fw pi-globe', url: ['https://www.google.com'], target: '_blank' },
                    { label: 'Bing', icon: 'pi pi-fw pi-comment', url: ['https://www.bing.com'] },
                ]
            }
        ]
    }
];

后端返回数据:

let badges={
    "/uikit/list": "23",
    "https://www.google.com": "NEW"
}

需要将数据更新为("/uikit/list"https://www.google.com 只有可能在某个多层嵌套项的 routerLinkurl 属性中):

let new_data = [
    {
        label: 'Home',
        items: [
            { label: 'Dashboard', icon: 'pi pi-fw pi-home', routerLink: ['/'] }
        ]
    },
    {
        label: 'UI Components',
        items: [
            { label: 'Form Layout', icon: 'pi pi-fw pi-id-card', routerLink: ['/uikit/formlayout'] },
            { label: 'Input', icon: 'pi pi-fw pi-check-square', routerLink: ['/uikit/input'] },
            { label: 'Float Label', icon: 'pi pi-fw pi-bookmark', routerLink: ['/uikit/floatlabel'] },
            { label: 'Invalid State', icon: 'pi pi-fw pi-exclamation-circle', routerLink: ['/uikit/invalidstate'] },
            { label: 'Button', icon: 'pi pi-fw pi-mobile', routerLink: ['/uikit/button'], class: 'rotated-icon' },
            { label: 'Table', icon: 'pi pi-fw pi-table', routerLink: ['/uikit/table'] },
        ]
    },
    {
        label: 'Blocks',
        items: [
            { label: 'List', icon: 'pi pi-fw pi-list', routerLink: ['/uikit/list'], badge: '23' },
            { label: 'Tree', icon: 'pi pi-fw pi-share-alt', routerLink: ['/uikit/tree'] },
            { label: 'Panel', icon: 'pi pi-fw pi-tablet', routerLink: ['/uikit/panel'] },
            
            { label: 'Google', icon: 'pi pi-fw pi-globe', url: ['https://www.google.com'], target: '_blank', badge: 'NEW' },
            { label: 'Bing', icon: 'pi pi-fw pi-comment', url: ['https://www.bing.com'] },
            
            {
                label: 'More',
                items: [
                    { label: 'List', icon: 'pi pi-fw pi-list', routerLink: ['/uikit/list'], badge: '23' },
                    
                    { label: 'Google', icon: 'pi pi-fw pi-globe', url: ['https://www.google.com'], target: '_blank', badge: 'NEW' },
                    { label: 'Bing', icon: 'pi pi-fw pi-comment', url: ['https://www.bing.com'] },
                ]
            }
        ]
    }
];

请问除了暴力的用 forEach 一项项遍历还有什么更优雅的做法么?

后端接口无法修改。

1926 次点击
所在节点    JavaScript
14 条回复
Kokororin
2022-04-15 00:11:39 +08:00
deepdash
Leviathann
2022-04-15 00:18:07 +08:00
...那放到 immer 里直接 flatmap 出 item 再遍历改值?
imycc
2022-04-15 00:19:34 +08:00
这个是描述目录的数据的,每个元素的规则都差不多,用递归处理,好像也不是很麻烦的样子?对于每个元素,碰到有 items 的就递归,没有的就判断 url 或者 routerLink 的值是否为目标值。
afewok
2022-04-15 00:55:38 +08:00
暴力的方式,难道不是字符串分割和拼接??
以 '/uikit/list'将这坨字符串分割成 2 个字符串,第一个串 + ], badge: '23' +第二个去掉 ], 的串,不就可以了。
rv54ntjwfm3ug8
2022-04-15 00:58:11 +08:00
@afewok #4 哈哈哈最早我也想到了这种方法,就是不便于维护,会被接手的骂
mxT52CRuqR6o5
2022-04-15 01:25:23 +08:00
肯定得遍历啊,先序遍历中序遍历后序遍历
GeruzoniAnsasu
2022-04-15 02:41:40 +08:00
先建倒排索引呗还能咋的,反正只遍历一次

反正架构方案就要求了前端必须完整存储所有 data ,那我为了加速多建几种用于索引的数据结构谁都 blame 不了吧
mind3x
2022-04-15 02:51:30 +08:00
jsonpath
chnwillliu
2022-04-15 06:39:29 +08:00
这 routerLink 数据量能有多大?上万?十万?遍历抗得住的。

看起来你这是要渲染导航栏,要不就不追求合并 badge 数据到树结构里?渲染导航节点的时候自己拿 url 去那个 map 里查有没有 badge 呗?
ChefIsAwesome
2022-04-15 09:06:41 +08:00
写俩函数,一个是把这种树形对象变成 html 。这样一来,增删改查的操作,可以直接用 dom api 。

<item label icon router>
<item label icon router></item>
<item label icon router></item>
</item>

然后再有一个函数能把这个 html 还原成 js 对象。实际也就遍历一遍,这一个是前面那个反过来而已。
renmu123
2022-04-15 09:19:48 +08:00
遍历就完事了
hazardous
2022-04-15 10:37:47 +08:00
@afewok 要先把对象序列化成字符串,这个恐怕比遍历慢多了。
Rache1
2022-04-15 13:39:49 +08:00
前段时间学到的,利用 JSON.parse 的第二个参数,试了一下,效果还可以。

```js
var data2 = JSON.parse(JSON.stringify(data), function (k, v) {
// 到顶层时返回
if (k === '') {
return v
}

if (k === 'items' && Array.isArray(v)) {
v.forEach(function (item) {
Object.keys(badges).forEach(function (badge) {
// 处理 routerLink
if (Array.isArray(item.routerLink) && item.routerLink.includes(badge)) {
Object.assign(item, { badge: badges[badge] })
}

// 处理 url
if (Array.isArray(item.url) && item.url.includes(badge)) {
Object.assign(item, { badge: badges[badge] })
}
})
})
}
return v
})
```
jjwjiang
2022-04-15 14:08:55 +08:00
遍历有啥不优雅的……直接用 array 的 api 呗

说实话我不是很明白一边觉得遍历不合适一边想着反复序列化反序列化……序列化的开销和不优雅程度可比遍历大多了……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/847043

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX