我有以下代码
<div class="gameContainer">
<span
v-for="(tile, index) in shuffledTiles"
:key="`${tile}_${index}`"
:data-key="`${tile}_${index}`"
:class="['tile-data px-2', tile, getClass(tile + index, tile)]"
@click="clickHandler(tile + index, tile)"
>
<img :src="`icons/${tile}.svg`" :alt="tile" />
</span>
</div>
呈现以上代码时,img src和alt值完全不同。我在shuffledTiles
中尝试了console.log,并在浏览器控制台中获得了值。一个是Nuxt SSR
,另一个是我的代码。两者的顺序完全不同。
如果您查看dom树,则数据键不同,图像src也不同。
您可以在此处https://github.com/stefanre1/game/blob/master/components/Game.vue
查看代码我不确定发生了什么。任何提示都会有所帮助。这是我的第一个项目。
答案 0 :(得分:1)
这是因为您要对瓷砖进行两次改组。在SSR期间一次,在客户端一次。
只做一次。一种简单的解决方案是将游戏组件包装在client-only组件中,从而仅在客户端渲染游戏组件
<client-only>
<game>
</client-only>
或者更好的方法是为游戏组件创建一个名为tiles
的道具。并且,在索引页的asyncData挂钩中计算该值。并将其作为道具传递给游戏组件。
在您的index.vue
中,添加
data: () => ({
tiles: null
}),
asyncData() {
const tilesData = [
'apple',
'orange',
'tomato',
'strawberry',
'tree',
'lemon'
]
const tiles = [...tilesData, ...tilesData]
for (let i = tiles.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1))
;[tiles[i], tiles[j]] = [tiles[j], tiles[i]]
}
return { tiles }
}
然后,将其作为道具传递给游戏组件
<game :tiles="tiles" />
然后,在game.vue组件中,将tiles
定义为prop并使用它。
props: {
tiles: {
type: Array,
required: true
}
},
环回tiles
而不是shuffledTiles
<span
v-for="(tile, index) in tiles"
:key="`${tile}_${index}`"
:data-key="`${tile}_${index}`"
:class="['tile-data px-2', tile, getClass(tile + index, tile)]"
@click="clickHandler(tile + index, tile)"
>
<img :src="`icons/${tile}.svg`" :alt="tile" />
</span>
之所以起作用,是因为asyncData
仅在页面加载时在服务器端执行。从asyncData返回的所有内容都将合并到页面组件的数据中。并且,传递给浏览器。因此,在浏览器上再次构建该应用程序时,它使用相同的数据,而不是构建一个新的数据。
PS。好像是一个有趣的游戏。祝你好运。 :)