Как сохранить состояние компонентов Svelte в виртуальном списке? - PullRequest
0 голосов
/ 05 октября 2018

Я разрабатываю компонент диаграммы Ганта в Svelte, и он состоит из сотен компонентов строки, каждый из которых содержит несколько компонентов задачи каждый.Задачи можно перетаскивать и перемещать.Производительность является приоритетом, и я использую виртуальный список для отображения только видимых строк.

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

Проблема в том, что когда я перемещаю задачи и прокручиваю строки из вида, они уничтожаются, а когда я возвращаюсь к ним, их состояние сбрасывается.Этот REPL с использованием svelte-virtual-list иллюстрирует проблему https://svelte.technology/repl?version=2.13.5&gist=bdb4c523d2e1cf7e3aef452e3f24d988 Мне интересно, как лучше всего справиться с этой ситуацией.

В настоящее время я использую объект задачи в качестве опоры и обновляю егоссылка остается прежней, а прокрутка не влияет на нее.

<Task {task}/>

Но внутри Задачи I обновляется состояние, подобное этому

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

, и шаблон ссылается на каждую подпорку с помощью task.propnameи я не уверен, что это правильный способ сделать это, так как не ясно, что именно устанавливается.

Я мог бы связать переменные задачи следующим образом:

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

Но многиепеременные должны быть привязаны (более 10), и я хочу позволить возможным будущим плагинам обновлять новые реквизиты из компонента Task.

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

Это касается потенциально большего количества реквизитов, но я обновляюОбъект задачи в событии состояния выглядит следующим образом:

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

Какой из них мне лучше выбрать для производительности или есть лучший способ справиться с этим?

1 Ответ

0 голосов
/ 21 апреля 2019

Вы должны изменить массив данных, а не изменять объект.Изменяя объект внутри массива, Svelte не знает, что ваш массив изменился.

Мутация массива будет происходить примерно так с Svelte v3 и использованием хранилища вместо plain-array:

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

...