在通过 Svelte 每个块迭代对象时查找值

Posted

技术标签:

【中文标题】在通过 Svelte 每个块迭代对象时查找值【英文标题】:Looking up values while iterating through an object via a Svelte each block 【发布时间】:2021-08-04 20:54:12 【问题描述】:

以下简化示例有效,但不确定它是否是最有效的方法,因为我在 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 作为键和 location 对象作为值填充 Map 对象,并在每个块中引用它。正在考虑它可能有更多的开销,因为我必须构建地图然后每次都通过键查找值。 在显示之前通过向部分对象添加位置属性来非规范化数据。当我传入数据时,不想对其进行变异或克隆的开销。 这个看起来很容易,但由于迭代可能效率较低...创建一个单元素数组,其中包含从 getLocation() 返回的位置对象,并使用内部每个块来访问这样的位置属性.. .
<template>
  #each schedule.sections as section
    #each [getLocation(section.locationId)] as location
      <p>location.name location.parking</p>
    /each
  /each
</template>

我是 Svelte 的新手。对最有效的方法有什么想法吗?我的第一种方法是不是最好的(或者我离基地还很远)?

【问题讨论】:

【参考方案1】:

我会说答案只取决于数据的情况。

我通常尽量避免使用任何函数作为模板的一部分(不包括操作)。这种默认做法来自使用 Vue2,其中计算的使用可以很容易地用于注入缓存数据,而不是在重新渲染时就地计算。不过,在 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

只要您在内部循环 (#each splitWord(word) as letter) 中有 &lt;input type="checkbox" bind:checked=somethingRandom&gt;,就会重新渲染内部循环。

如果您将内部somethingRandom 输入注释掉并且只将它放在外部循环中,则更改somethingRandom 值不会导致内部循环重新呈现。

但是更改 &lt;input bind:value=word&gt; 会导致内部重新渲染

整个list 总是重新渲染

因此,如果您有一个庞大的数据集并且正在编辑 schedule.sections 和/或 schedule.locations,那么您可能需要考虑添加某种形式的缓存。 Svelte 监视整个数组或对象的更改,因此如果您想实现可以根据单个项目更改进行缓存的东西,您可能需要手动实现很多缓存机制。

如果数据按时呈现,并且它没有改变,那么缓存或反规范化几乎没有好处(无论如何就性能而言)。

【讨论】:

以上是关于在通过 Svelte 每个块迭代对象时查找值的主要内容,如果未能解决你的问题,请参考以下文章

在带有 Svelte 的每个块中使用定义的变量

Python列表操作

数据对象未在 Svelte 组件中呈现

启用多重选择后如何从velve-select组件中获取所有值

如何在一组对象中查找特定值?

for...of语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语