我是Svelte的新手,我尝试了一个微不足道的Tic实现。
我不明白为什么当我更新数组的元素时,反应性是有效的,这与文档中所说的必须将数组分配给自己来触发订阅通知相反。
我不能为应用程序设置REPL,因为我使用的是类型记录,Svelte似乎只支持JS,所以我希望这个主Board.svelte文件足够了,因为这似乎是问题所在。
我的问题与tiles
数组有关,该数组是在单击处理程序中更新的。请注意,单击处理程序不是反应性的(没有$:
,不是倾斜函数,而不是箭头函数),但是对tiles[index]
的修改似乎会导致反应性,因为UI更新了,而且每当董事会更改时也会计算gameOver
变量(如果游戏正在进行,则返回undefined
,或者包含获胜玩家和构成获胜的平铺索引的对象)。
请注意,isWin
函数是使用反应性编写的--如果我删除$:
,它将停止更新瓷砖上的isWin
支柱,后者控制在游戏结束时是否突出显示该瓷砖。
这似乎是矛盾的-- gameOver
需要将tiles
作为参数传递,并标记为reactive,否则它不会对平铺更新做出反应(正如我所期望的)。isWin
需要是反应性的,否则不会导致Tile
重新呈现。
但是我无法解释为什么当数组本身没有更新(只有元素)时,click
设法触发更新。注意:删除对gameOver
和activePlayer
的引用对tiles
上的订阅通知没有任何影响。
我特别避免在这个实现中使用svelte/store。我在试图使用它们时陷入了困境,并将其剥离回基本的反应性,发现它完成了我所需的一切,并且我不清楚在使用存储和反应性vars时,'array = array‘约定是否不同。
在继续前进之前,我真的很想更好地理解这一点。
<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>
发布于 2022-08-01 09:53:52
分配数组的元素就像分配任何其他对象属性一样,因此数组将被标记为脏。
文档警告的是在内部更改数组的函数的使用,例如push
或pop
。这将要求Svelte知道各种功能如何保持反应性。
Svelte对代码进行分析,以查看状态修改的发生位置。
<script>
let items = ['a', 'b', 'c'];
</script>
<button on:click={() => items[0] = '!'}>
Change Item 0
</button>
这里,click处理程序的编译代码将包含使items
无效的附加逻辑,因为它的属性'0'
已被修改。
function instance($$self, $$props, $$invalidate) {
let items = ['a', 'b', 'c'];
const click_handler = () => $$invalidate(0, items[0] = '!', items);
return [items, click_handler];
}
无论对象是数组还是添加了其他嵌套属性,都会发生这种情况。
https://stackoverflow.com/questions/73197602
复制相似问题