Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在虚拟列表中保持苗条组件的状态?_Javascript_Svelte_Virtualscroll - Fatal编程技术网

Javascript 如何在虚拟列表中保持苗条组件的状态?

Javascript 如何在虚拟列表中保持苗条组件的状态?,javascript,svelte,virtualscroll,Javascript,Svelte,Virtualscroll,我正在用Svelte开发一个甘特图组件,它由100个行组件组成,每个行组件包含多个任务组件。可以拖动和移动任务。性能是一个优先事项,我使用虚拟列表只渲染可见的行 <div class="scrollable"> {#each visibleRows as row (row.id)} <div class="row"> {#each row.tasks as task (task.id)} &l

我正在用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>
模板引用了task.propname中的每个道具,我不确定这是否是最简单的方式,因为不清楚到底设置了什么

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

const {task} = this.get();
task.from = new Date();
this.set({task});
<Task bind:from=task.from 
      bind:to={task.to}/>

为了提高性能,我应该选择哪种方法?或者有更好的方法来处理这个问题?

您应该更改数据数组,而不是改变对象。通过改变数组中的对象,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>
//data.js
...
从'svelte/store'导入{writable};
导出默认可写(getData())
...
//App.svelte
...
从“/data.js”导入项目;
函数更新内容(项){
常量索引=$items.indexOf(item)
$items=[
…$items.slice(0,索引),
{…项,内容:'更新内容'},
…$items.slice(索引+1)
]
}
...
...
updateContent(项目)}>更新内容
...
完整示例:


您可以在此处阅读有关更新数组和对象的更多信息:

似乎您没有选择使用onstate事件。您在使用onstate事件时遇到了什么问题?对此有任何更新吗?我将继续使用第一种方法,但将
任务
属性重命名为_task、_data或_state,以进一步将其区分为某种“受保护状态”属性。使用
onstate
的最后一种方法会在每次状态更改时触发,即使是那些不应该更新
task
,并且很容易在其中包含不必要的数据…在您的示例中,
items
data.js
中实例化,不是吗?你为什么在
updateContent
中调用
$items
,而不是
items
<Task {task} 
      {...task}/>
onstate({ changed, current, previous }) {
    const {task} = this.get();
    Object.assign(task, current);
    this.set({task});
},
// 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>