可变数据的怪异行为

时间:2019-10-27 12:57:02

标签: vue.js nuxt.js

我有以下代码

    <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

查看代码

我不确定发生了什么。任何提示都会有所帮助。这是我的第一个项目。

enter image description here

1 个答案:

答案 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。好像是一个有趣的游戏。祝你好运。 :)