Svelte Kit嵌套each循环如何获取全局连续唯一索引
Svelte嵌套循环生成图片全局唯一索引实现方案
业务场景
开发图片上传类网站,核心数据结构规则如下:
- 支持创建相册
- 每个相册可包含多篇帖子
- 每篇帖子通过
images数组存储多张图片链接
现有示例数据:
const albums = [ { id: 1, title: 'Album 1', } ] const posts = [ { "album": 1, "images": [ "https://picsum.photos/200/300", "https://picsum.photos/200/300", ], "author": 1, }, { "album": 1, "images": [ "https://picsum.photos/200/300", ], "author": 2, }, { "album": 1, "images": [ "https://picsum.photos/200/300", "https://picsum.photos/200/300", "https://picsum.photos/200/300", "https://picsum.photos/200/300", "https://picsum.photos/200/300", ], "author": 4, } ]
问题描述
最初通过Svelte嵌套#each循环渲染图片,直接使用内层循环的index作为图片编号:
{#each posts as post} {#each post.images as image, index} {index}: {image} {/each} {/each}
该写法的index是单篇帖子范围内的局部索引,每遍历一篇新帖子索引会从0重新计数,导致索引重复,实际输出如下:
0: https://picsum.photos/200/300 1: https://picsum.photos/200/300 0: https://picsum.photos/200/300 0: https://picsum.photos/200/300 1: https://picsum.photos/200/300 2: https://picsum.photos/200/300 3: https://picsum.photos/200/300 4: https://picsum.photos/200/300
预期输出为从0开始连续递增、无重复的全局索引,效果如下:
0: https://picsum.photos/200/300 1: https://picsum.photos/200/300 2: https://picsum.photos/200/300 3: https://picsum.photos/200/300 4: https://picsum.photos/200/300 5: https://picsum.photos/200/300 6: https://picsum.photos/200/300 7: https://picsum.photos/200/300
实现方案
方案1:预处理为扁平图片数组(推荐)
通过数组方法提前把嵌套的图片结构转换为单图对应一条记录的扁平数组,遍历该数组时自带的索引就是全局连续的唯一索引,性能最优。
可以直接用flatMap实现,写法最简洁:
// 预处理生成扁平图片列表,可保留原帖子的关联字段 const flatImages = posts.flatMap(post => post.images.map(imgUrl => ({ url: imgUrl, albumId: post.album, authorId: post.author })) )
Svelte模板中直接遍历扁平数组即可:
{#each flatImages as image, globalIndex} {globalIndex}: {image.url} {/each}
如果运行环境不支持flatMap,可以用reduce实现等价逻辑:
const flatImages = posts.reduce((acc, post) => { const postImages = post.images.map(imgUrl => ({ url: imgUrl, albumId: post.album, authorId: post.author })) return acc.concat(postImages) }, [])
方案2:循环内计算索引偏移量(无数据预处理)
如果不想改动原数据结构,可以在循环时计算当前帖子之前所有图片的总数量作为偏移量,和内层循环的局部索引相加得到全局索引:
{#each posts as post, postIndex} <!-- 计算当前帖子之前所有图片的总数,作为索引偏移值 --> {@const offset = posts.slice(0, postIndex).reduce((sum, p) => sum + p.images.length, 0)} {#each post.images as image, localIndex} {@const globalIndex = offset + localIndex} {globalIndex}: {image} {/each} {/each}
该方案每次渲染都会重复计算偏移量,数据量较大时渲染性能低于预处理方案,仅适合小规模数据场景使用。
内容的提问来源于stack exchange,提问作者Wolf
相关产品推荐
相关产品推荐

