将项目附加到 Svelte Store 中的最后一个对象

Append item to last object in Svelte Store

我正在尝试创建一个 Svelte 应用程序,它将国际象棋的走法存储在一个数组中。每次创建新的白棋时,都应在数组中创建一个新对象。创建黑棋应该简单地更新最后一个对象中的字段 black_move。但是,在再次按下白色移动按钮之前,输出不会对此更新做出反应。可能是什么问题? REPL 是 here.

import { writableArray } from './store.js';
    
    const moveWhite = () => {
        $writableArray = [...$writableArray, {
            white_move: 'a1-a2',
            black_move: ''
        }];
    };
    const moveBlack = () => {
        $writableArray.at(-1).black_move = 'b1-b2' 
    };
  
<button on:click={moveWhite}>
    Move White
</button>
<button on:click={moveBlack}>
    Move Black
</button>

{#each $writableArray as item}
    {item.white_move} {item.black_move}
{/each}

店铺定义如下:

import { writable } from 'svelte/store';

export const writableArray = writable([]);

您可以使用 update 方法,例如:

writableArray.update(existingValue => ([...existingValue, newMove]));

因此,对于您的示例,它可能如下所示:

<script>
    import { writableArray } from './store.js';
    
    const moveWhite = () => {   
        writableArray.update(s => ([...s, {
            white_move: 'a1-a2',
            black_move: ''
        }]));
    };
    
    const moveBlack = () => {       
        writableArray.update(s => {
            s.at(-1).black_move = 'b1-b2'           
            
            return s
        });
    };
</script>

我发现以下方法也有效,但由于我是 Svelte 的新手,我不确定这是推荐的方法:

const moveBlack = () => {
        $writableArray.at(-1).black_move = 'b1-b2' 
        $writableArray = [...$writableArray]
    };

我认为使用作业

const moveBlack = () => {
        $writableArray.at(-1).black_move = 'b1-b2' 
        $writableArray = $writableArray
    };

是一个很好的组件内部解决方案,因为它比使用 .update() 更简洁。就像已经提到的那样,扩展运算符不是必需的,重要的是赋值。查看文档 'assignments are "reactive"'

并且展示另一种方法,而不是在 App.svelte 中声明函数,您还可以创建一个自定义存储并将它们放在那里 -> REPL

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

export const movesArray = (() => {
    const {subscribe, set, update} = writable([])
    return {
        subscribe,
//      set, // optional if needed outside store
//      update, // optional if needed outside store
        moveWhite() {
            update(store => {
                return [...store, { white_move: 'a1-a2', black_move: ''}]
            })
        },
        moveBlack(move) {
            update(store => {
                store.at(-1).black_move = move
                return store // this line is important
            })
        }       
    }   
})();
App.svelte
<script>
    import { movesArray } from './store.js';        
</script>

<button on:click={movesArray.moveWhite}>
    Move White
</button>
<button on:click={() => movesArray.moveBlack('b1-b2')}>
    Move Black
</button>

{#each $movesArray as item}
<p>
    {item.white_move} {item.black_move}
</p>
{/each}