简体   繁体   English

为什么重新渲染组件后 Vue 道具不重置?

[英]Why isn't Vue prop resetting after re-rendering component?

I am trying to create a board that can change size at the click of a button.我正在尝试创建一个可以通过单击按钮更改大小的板。 The board has width and height attributes that determine how many cells wide and tall it is.该板具有宽度和高度属性,这些属性确定它的宽度和高度有多少单元格。 When I change these width and height attributes, the board re-renders to the proper size, but its props (namely a coords prop that is an [x,y] array of the position of the cell on the board) does not update properly.当我更改这些宽度和高度属性时,板子会重新渲染为正确的大小,但它的道具(即一个 coords 道具,它是板上单元格的 position 的 [x,y] 数组)没有正确更新.

When the page first renders (with a board width and height of 10) and I console.log the cells of the board, the top-left cell has the coordinates of [0,0], which is correct.当页面第一次呈现时(板的宽度和高度为 10)并且我 console.log 板的单元格,左上角的单元格的坐标为 [0,0],这是正确的。 screenshot.截屏。

However, after resetting the width and height to 5 each, the top-left cell has coords of [4,0], and I don't understand why.但是,在将宽度和高度分别重置为 5 后,左上角的单元格的坐标为 [4,0],我不明白为什么。 screenshot.截屏。

Here is my code for App.vue:这是我的 App.vue 代码:

 <template> <button @click="resetBoard()">reset game with new board dimensions</button> <div:style="{ width: boardWidth, height: boardHeight }"> <div v-for="y in height":key="y"> <BoardCell v-for="x in width" ref="cells":coords="[x - 1, y - 1]":key="y * width + x" /> </div> </div> <button @click="logCells">log cells to console</button> </template> <script> import BoardCell from "./components/BoardCell.vue"; export default { name: "App", components: { BoardCell }, data() { return { width: 10, height: 10, }; }, computed: { boardWidth() { return (this.width * 40).toString() + "px"; }, boardHeight() { return (this.height * 40).toString() + "px"; }, }, methods: { resetBoard() { this.width = 5; this.height = 5; }, logCells(){ console.log('this.$refs.cells:') console.log(this.$refs.cells) } }, }; </script>

And here is my code for the cell component:这是我的单元组件代码:

 <template> <div class="cell"> </div> </template> <script> export default { props: ['coords'] } </script> <style scoped>.cell { width: 40px; height: 40px; float: left; line-height: 0px; background-color: limegreen; border: 1px green solid; box-sizing: border-box; } </style>

I think the issue may be connected to the key :key="y * width + x" .我认为这个问题可能与关键:key="y * width + x"有关。 It is probably not unique.它可能不是唯一的。

When you change the size of the board the Vue renderer tries to reuse the elements from the previous board, and because the previous board has the elements with the same keys you may see old elements in your new board.当您更改板子的大小时,Vue 渲染器会尝试重用前一个板子中的元素,并且由于前一个板子具有相同键的元素,您可能会在新板子中看到旧元素。

For example:例如:

  • you had a board 10x10, then key for element [1][1] is :key="11"你有一块 10x10 的板,那么元素 [1][1] 的键是:key="11"
  • for a new board 5x5, the key for element [2][1] is :key="11" as well, so Vue renderer will reuse the old element here.对于 5x5 的新板,元素 [2][1] 的键也是:key="11" ,因此 Vue 渲染器将在此处重用旧元素。

To avoid it I think you should try to create keys that will be unique for different boards为避免这种情况,我认为您应该尝试为不同的板创建唯一的密钥

An example一个例子

<div v-for="y in height" :key="`${height}x${width}[${y}]`">
  <BoardCell
    v-for="x in width"
    ref="cells"
    :coords="[x - 1, y - 1]"
    :key="`${height}x${width}[${y}][${x}]`"
  />
</div>

In that example you going to have keys like 10x10[1][1] or 5x5[2][1] .在该示例中,您将拥有10x10[1][1]5x5[2][1]类的键。

Actually, the ref you're console logging is not the top left cell but the top right.实际上,您在控制台记录的 ref 不是左上角的单元格,而是右上角。 The order of the $refs array used in a v-for is not guaranteed to match the source array. v-for 中使用的 $refs 数组的顺序不能保证与源数组匹配。 According to the docs :根据文档

$refs are only populated after the component has been rendered, and they are not reactive. $refs 仅在组件被渲染后才被填充,并且它们不是响应式的。 It is only meant as an escape hatch for direct child manipulation - you should avoid accessing $refs from within templates or computed properties.它仅作为直接子操作的逃生舱口 - 您应该避免从模板或计算属性中访问 $refs。

I threw your code in a sandbox and using Vue DevTools I verified the coordinates of the top left cell are correct using the component inspector which you can see here (I changed the color to make the cell highlighting easier to see)我将您的代码放入沙箱并使用Vue DevTools我使用组件检查器验证了左上角单元格的坐标是否正确,您可以在此处看到(我更改了颜色以使单元格突出显示更容易看到)

If you really need to keep track of the cells and their proper order you could make an array of "Cell" objects.如果您确实需要跟踪单元格及其正确顺序,您可以制作一组“单元格”对象。 It looks like you could benefit from this where each object could perhaps store it's own coordinate.看起来您可以从中受益,每个 object 都可以存储它自己的坐标。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM