在通过 Svelte each 块遍历对象时查找值
Looking up values while iterating through an object via a Svelte each block
以下简化示例有效,但不确定它是否是最有效的方法,因为我在每次迭代的每个块中多次调用 getLocation():
<script>
export let schedule = {
locations: [
{
_id: 1,
name: 'Boston',
parking: 'Onstreet'
},
{
_id: 2,
name: 'New York',
parking: 'Paid lot'
}
],
sections: [
{
locationId: 2,
day: 1
},
{
locationId: 1,
day: 2
}
]
}
function getLocation(id) {
return schedule.locations.find( ({ _id }) => _id === id )
}
</script>
<template>
{#each schedule.sections as section}
<p>{getLocation(section.locationId).name} {getLocation(section.locationId).parking}</p>
{/each}
</template>
我可以使用的其他方法:
- 使用 locationId 作为键和位置对象作为值填充一个 Map 对象,并在每个块中引用它。我认为它可能有更多的开销,因为我必须构建地图,然后每次都要按键查找值。
- 通过在显示前向节对象添加位置属性来对数据进行非规范化。当我传递数据时,不想改变它或有克隆的开销。
- 这个看起来很容易,但由于迭代可能效率较低...创建一个单元素数组,其中包含从 getLocation() 返回的位置对象,并使用内部每个块来访问这样的位置属性...
<template>
{#each schedule.sections as section}
{#each [getLocation(section.locationId)] as location}
<p>{location.name} {location.parking}</p>
{/each}
{/each}
</template>
我是 Svelte 的新手。关于最有效的方法是什么有什么想法吗?我的第一种方法是最好的吗(或者我偏离了基础)?
我会说答案只取决于数据中发生的事情。
我通常尽量避免使用任何功能作为模板的一部分(不包括动作)。这种默认做法来自于使用 Vue2,其中使用 computed 可以很容易地用于注入缓存数据,而不是在重新渲染时就地计算。不过,在 svelte 中,我发现反应性在确定组件中要更新的部分方面做得很好。
这是一个示例(复制粘贴到 repl)
<script>
const list = ['uno', 'dos', 'tres', 'catorce'];
let somethingRandom = true
const splitWord = (word) => {
console.log(`split [${word}]`)
return word.split('')
};
</script>
{#each list as word}
<div>
{#each splitWord(word) as letter}
<span>{letter}</span>
<input type="checkbox" bind:checked={somethingRandom}> <!-- causes re-render-->
{/each}
</div>
<input bind:value={word}> <!-- causes re-render -->
<input type="checkbox" bind:checked={somethingRandom}><!-- does not cause to re-render -->
{/each}
只要在内循环中有<input type="checkbox" bind:checked={somethingRandom}>
({#each splitWord(word) as letter}
),内循环就会重新渲染
如果您将内部 somethingRandom
输入注释掉并且仅在外部循环中使用它,则更改 somethingRandom
值将不会导致内部循环重新呈现。
更改 <input bind:value={word}>
然而会导致内部重新渲染
整个list
总是重新渲染
因此,如果您有一个庞大的数据集并且正在编辑 schedule.sections
and/or schedule.locations
,那么您可能需要考虑添加某种形式的缓存。 Svelte 监视整个数组或对象的变化,所以如果你想实现可以根据单个项目变化进行缓存的东西,你可能需要手动实现很多缓存机制。
如果数据按时呈现且未更改,则缓存或反规范化几乎没有好处(无论如何在性能方面)。
以下简化示例有效,但不确定它是否是最有效的方法,因为我在每次迭代的每个块中多次调用 getLocation():
<script>
export let schedule = {
locations: [
{
_id: 1,
name: 'Boston',
parking: 'Onstreet'
},
{
_id: 2,
name: 'New York',
parking: 'Paid lot'
}
],
sections: [
{
locationId: 2,
day: 1
},
{
locationId: 1,
day: 2
}
]
}
function getLocation(id) {
return schedule.locations.find( ({ _id }) => _id === id )
}
</script>
<template>
{#each schedule.sections as section}
<p>{getLocation(section.locationId).name} {getLocation(section.locationId).parking}</p>
{/each}
</template>
我可以使用的其他方法:
- 使用 locationId 作为键和位置对象作为值填充一个 Map 对象,并在每个块中引用它。我认为它可能有更多的开销,因为我必须构建地图,然后每次都要按键查找值。
- 通过在显示前向节对象添加位置属性来对数据进行非规范化。当我传递数据时,不想改变它或有克隆的开销。
- 这个看起来很容易,但由于迭代可能效率较低...创建一个单元素数组,其中包含从 getLocation() 返回的位置对象,并使用内部每个块来访问这样的位置属性...
<template>
{#each schedule.sections as section}
{#each [getLocation(section.locationId)] as location}
<p>{location.name} {location.parking}</p>
{/each}
{/each}
</template>
我是 Svelte 的新手。关于最有效的方法是什么有什么想法吗?我的第一种方法是最好的吗(或者我偏离了基础)?
我会说答案只取决于数据中发生的事情。
我通常尽量避免使用任何功能作为模板的一部分(不包括动作)。这种默认做法来自于使用 Vue2,其中使用 computed 可以很容易地用于注入缓存数据,而不是在重新渲染时就地计算。不过,在 svelte 中,我发现反应性在确定组件中要更新的部分方面做得很好。
这是一个示例(复制粘贴到 repl)
<script>
const list = ['uno', 'dos', 'tres', 'catorce'];
let somethingRandom = true
const splitWord = (word) => {
console.log(`split [${word}]`)
return word.split('')
};
</script>
{#each list as word}
<div>
{#each splitWord(word) as letter}
<span>{letter}</span>
<input type="checkbox" bind:checked={somethingRandom}> <!-- causes re-render-->
{/each}
</div>
<input bind:value={word}> <!-- causes re-render -->
<input type="checkbox" bind:checked={somethingRandom}><!-- does not cause to re-render -->
{/each}
只要在内循环中有
<input type="checkbox" bind:checked={somethingRandom}>
({#each splitWord(word) as letter}
),内循环就会重新渲染如果您将内部
somethingRandom
输入注释掉并且仅在外部循环中使用它,则更改somethingRandom
值将不会导致内部循环重新呈现。更改
<input bind:value={word}>
然而会导致内部重新渲染整个
list
总是重新渲染
因此,如果您有一个庞大的数据集并且正在编辑 schedule.sections
and/or schedule.locations
,那么您可能需要考虑添加某种形式的缓存。 Svelte 监视整个数组或对象的变化,所以如果你想实现可以根据单个项目变化进行缓存的东西,你可能需要手动实现很多缓存机制。
如果数据按时呈现且未更改,则缓存或反规范化几乎没有好处(无论如何在性能方面)。