【问题标题】:How to persist state of Svelte components in a virtual list?如何在虚拟列表中保留 Svelte 组件的状态?
【发布时间】:2019-03-10 19:28:10
【问题描述】:

我正在 Svelte 中开发一个甘特图组件,它由 100 个行组件组成,每个行组件都包含多个任务组件。可以拖动和移动任务。性能是重中之重,我使用虚拟列表仅呈现可见行。

<div class="scrollable">
    {#each visibleRows as row (row.id)}
        <div class="row">
            {#each row.tasks as task (task.id)}
                <Task from={task.from} to={to}/>
            {/each}
        </div>
    {/each}
</div>

问题是当我移动任务并将行滚动出视图时,它们会被破坏,当我滚动回它们时,它们的状态会被重置。这个使用 svelte-virtual-list 的 REPL 说明了问题https://svelte.technology/repl?version=2.13.5&gist=bdb4c523d2e1cf7e3aef452e3f24d988 我想知道处理这种情况的最佳方法是什么。

目前我正在使用任务对象作为道具并对其进行更新,引用保持不变并且滚动不会影响它。

<Task {task}/>

但在任务中我像这样更新状态

const {task} = this.get();
task.from = new Date();
this.set({task});

并且模板使用 task.propname 引用每个道具,我不确定它是否是这样做的苗条方式,因为不清楚究竟设置了什么。

我可以像这样绑定任务变量

<Task bind:from=task.from 
      bind:to={task.to}/>

但是需要绑定很多变量(超过 10 个),我希望未来可能的插件可以从 Task 组件内部更新新的 props。

<Task {task} 
      {...task}/>

这处理潜在的更大数量的道具,但我像这样更新状态事件中的任务对象:

onstate({ changed, current, previous }) {
    const {task} = this.get();
    Object.assign(task, current);
    this.set({task});
},

我应该更喜欢哪一个来提高性能,或者有更好的方法来处理这个问题?

【问题讨论】:

  • 似乎您别无选择使用 onstate 事件。您在使用 onstate 事件时遇到了什么问题?
  • 这方面有什么更新吗?
  • 我将继续使用第一种方法,但将 task 属性重命名为 _task、_data 或 _state 以进一步将其区分为某种“受保护状态”属性。 onstate 的最后一种方法会在每次状态更改时触发,即使是那些不应该最终更新 task 的方法,并且很容易在其中包含不必要的数据...

标签: javascript svelte virtualscroll


【解决方案1】:

你应该改变数据数组而不是改变对象。通过改变数组中的对象,Svelte 不知道你的数组已经改变了。

使用 Svelte v3 并使用存储而不是普通数组来改变数组:

// data.js
...
import { writable } from 'svelte/store';

export default writable(getData())
...

// App.svelte
<script>
...
import items from './data.js';

function updateContent(item) {
    const index = $items.indexOf(item)
    $items = [
        ...$items.slice(0, index),
        { ...item, content: 'updated content' },
        ...$items.slice(index + 1)
    ]
}
...
</script>

<VirtualList items={$items} let:item bind:start bind:end>
    ...
        <button on:click={() => updateContent(item)}>update content</button>
    ...
</VirtualList>

完整示例:https://svelte.dev/repl?version=3.0.0-beta.28&gist=f8c7e96bb34906db2c3a5e85b4840017

您可以在此处阅读有关更新数组和对象的更多信息:https://svelte.dev/tutorial/updating-arrays-and-objects

【讨论】:

  • 在您的示例中,itemsdata.js 中实例化的位置在哪里,不是,对吧?你怎么会在updateContent 中调用$items 而不是items
猜你喜欢
  • 1970-01-01
  • 2018-12-21
  • 2020-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-22
  • 2014-11-05
相关资源
最近更新 更多