简体   繁体   English

如何在虚拟列表中保留 Svelte 组件的状态?

[英]How to persist state of Svelte components in a virtual list?

I'm developing a gantt chart component in Svelte and it consists of 100s of row components each containing multiple task components each.我正在 Svelte 中开发甘特图组件,它由 100 个行组件组成,每个组件包含多个任务组件。 Tasks can be dragged and moved.可以拖动和移动任务。 Performance is a priority and I am using a virtual list to render only the visible rows.性能是重中之重,我使用虚拟列表仅呈现可见行。

<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>

The problem is when I move tasks around and scroll rows out of the view, they get destroyed, and when I scroll back to them, their state gets reset.问题是当我四处移动任务并将行滚动到视图之外时,它们会被破坏,而当我回滚到它们时,它们的状态会被重置。 This REPL using svelte-virtual-list illustrates the problem https://svelte.technology/repl?version=2.13.5&gist=bdb4c523d2e1cf7e3aef452e3f24d988 I am wondering what is the best way to deal with this situation.这个使用 svelte-virtual-list 的 REPL 说明了这个问题https://svelte.technology/repl?version=2.13.5&gist=bdb4c523d2e1cf7e3aef452e3f24d988我想知道处理这种情况的最佳方法是什么。

Currently I'm using the task object as prop and updating it, the reference keeps the same and scrolling doesn't affect it.目前我正在使用任务对象作为道具并更新它,引用保持不变并且滚动不会影响它。

<Task {task}/>

But inside Task I update state like this但是在 Task 中,我像这样更新状态

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

and the template references every prop with task.propname and I'm not sure if it's the svelte way of doing it as it is not clear what exactly gets set.并且模板使用 task.propname 引用每个道具,我不确定这是否是一种简洁的方式,因为不清楚究竟设置了什么。

I could bind task variables like this我可以像这样绑定任务变量

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

But a lot of variables need to be bind (more than 10), and I want to allow possible future plugins update new props from inside the Task component.但是需要绑定很多变量(超过 10 个),我希望将来可能的插件从 Task 组件内部更新新的 props。

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

This deals with potential bigger number of props, but I update the task object in the state event like this:这处理潜在的更大数量的道具,但我更新状态事件中的任务对象,如下所示:

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

Which of these should I prefer for performance or is there a better way to handle this?我应该更喜欢哪一个来提高性能,或者有更好的方法来处理这个问题?

You should alter the array of data instead of mutating the object.您应该改变数据数组而不是改变对象。 By mutating the object inside the array, Svelte does not know that your array has changed.通过改变数组内的对象,Svelte 不知道您的数组已更改。

Mutating the array would go something like this with Svelte v3 and using a store instead of plain-array:使用 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>

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM