首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >数组元素Svelte赋值中看似矛盾的反应性

数组元素Svelte赋值中看似矛盾的反应性
EN

Stack Overflow用户
提问于 2022-08-01 09:43:00
回答 1查看 54关注 0票数 0

我是Svelte的新手,我尝试了一个微不足道的Tic实现。

我不明白为什么当我更新数组的元素时,反应性是有效的,这与文档中所说的必须将数组分配给自己来触发订阅通知相反。

我不能为应用程序设置REPL,因为我使用的是类型记录,Svelte似乎只支持JS,所以我希望这个主Board.svelte文件足够了,因为这似乎是问题所在。

我的问题与tiles数组有关,该数组是在单击处理程序中更新的。请注意,单击处理程序不是反应性的(没有$:,不是倾斜函数,而不是箭头函数),但是对tiles[index]的修改似乎会导致反应性,因为UI更新了,而且每当董事会更改时也会计算gameOver变量(如果游戏正在进行,则返回undefined,或者包含获胜玩家和构成获胜的平铺索引的对象)。

请注意,isWin函数是使用反应性编写的--如果我删除$:,它将停止更新瓷砖上的isWin支柱,后者控制在游戏结束时是否突出显示该瓷砖。

这似乎是矛盾的-- gameOver需要将tiles作为参数传递,并标记为reactive,否则它不会对平铺更新做出反应(正如我所期望的)。isWin需要是反应性的,否则不会导致Tile重新呈现。

但是我无法解释为什么当数组本身没有更新(只有元素)时,click设法触发更新。注意:删除对gameOveractivePlayer的引用对tiles上的订阅通知没有任何影响。

我特别避免在这个实现中使用svelte/store。我在试图使用它们时陷入了困境,并将其剥离回基本的反应性,发现它完成了我所需的一切,并且我不清楚在使用存储和反应性vars时,'array = array‘约定是否不同。

在继续前进之前,我真的很想更好地理解这一点。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script lang="ts">
    import Tile from './Tile.svelte'
    import Result from "./Result.svelte"
    import Reset from "./Reset.svelte"
    import type { GameOver, Player } from "./types"
    import { getGameOver } from "./getGameOver"

    let activePlayer: Player = 'X'
    const tiles: Array<Player | undefined> = Array(9).fill(undefined)

    let gameOver: GameOver | undefined
    $: gameOver = getGameOver(tiles)

    let isWin: (index: number) => boolean
    $: isWin = (index: number) => {
        return gameOver?.winLine?.includes(index) ?? false
    }

    function click(index: number) {
        if (!gameOver && tiles[index] === undefined) {
            tiles[index] = activePlayer
            activePlayer = activePlayer === 'X' ? 'O' : 'X'
        }
    }

    function reset() {
        for (const index in tiles) {
            tiles[index] = undefined
        }
        activePlayer = 'X'
    }

</script>

<div class="board" class:gameOver={!!gameOver}>
    <Result gameOver={gameOver} activePlayer={activePlayer}/>

    <div class="tiles">
        {#each tiles as tile, i}
            <Tile player={tile} isWin={isWin(i)} click={() => click(i)}/>
        {/each}
    </div>
    <Reset reset={reset}/>
</div>

<style>
    .tiles {
        display: grid;
        grid-template-columns: repeat(3, 100px);
        grid-template-rows: repeat(3, 100px);
    }
</style>
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-01 09:53:52

分配数组的元素就像分配任何其他对象属性一样,因此数组将被标记为脏。

文档警告的是在内部更改数组的函数的使用,例如pushpop。这将要求Svelte知道各种功能如何保持反应性。

Svelte对代码进行分析,以查看状态修改的发生位置。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script>
    let items = ['a', 'b', 'c'];
</script>

<button on:click={() => items[0] = '!'}>
    Change Item 0
</button>

这里,click处理程序的编译代码将包含使items无效的附加逻辑,因为它的属性'0'已被修改。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function instance($$self, $$props, $$invalidate) {
    let items = ['a', 'b', 'c'];
    const click_handler = () => $$invalidate(0, items[0] = '!', items);
    return [items, click_handler];
}

无论对象是数组还是添加了其他嵌套属性,都会发生这种情况。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73197602

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文