【问题标题】:Looking up values while iterating through an object via a Svelte each block在通过 Svelte 每个块迭代对象时查找值
【发布时间】: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>

我可以使用的其他方法:

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

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

【问题讨论】:

    标签: arrays object each svelte svelte-3


    【解决方案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 监视整个数组或对象的更改,因此如果您想实现可以根据单个项目更改进行缓存的东西,您可能需要手动实现很多缓存机制。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-17
      • 2017-05-10
      • 2018-09-02
      • 1970-01-01
      • 2018-12-06
      • 2018-04-05
      • 1970-01-01
      • 2017-12-16
      相关资源
      最近更新 更多