A very confusing bug's creeping into my vue component; if I add line 5 from the code below, it works as expected, if I remove it, the click method for each board-slot
element stops changing the boardSlots
object.
What does using {{currentPlayer}}
have to do with this? I'm not using it anywhere else. It doesn't necessarily need to be printed, just needs to be somewhere in the template's definition, so a random element with a class binding of currentPlayer
also miraculously makes it work. Is there something about Vuex's architecture that I'm missing?
<template>
<div id="board-container">
//THIS LINE
{{currentPlayer}}
<div id="board">
<div class="board-row" v-for="i in boardSlots">
<div class="board-slot"
v-for="boardSlot in i"
:class="[{checked: (boardSlot.owner != 0)}, 'ownedBy-player-' + boardSlot.owner]"
@click="checkSlot(boardSlot.row, boardSlot.col)">
</div>
</div>
</div>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default{
created(){
for(var i = 0; i < 6; i++){
this.boardSlots[i] = [];
}
var row = 0;
var col = 0;
for(var i = 1; i <= 42; i++){
this.boardSlots[row].push({
owner: 0,
hover: false,
row: row,
col: col,
});
col++;
if (col == 7) {
col = 0;
if (row < 5) {
row++;
}
}
}
},
data(){
return {
boardSlots: [],
}
},
computed: {
...mapState([
'currentPlayer',
]),
},
methods: {
...mapActions([
'swapToNextPlayer',
]),
checkSlot(row, col){
if (this.boardSlots[row][col].owner == 0) {
this.boardSlots[row][col].owner = 1;
this.swapToNextPlayer();
}
}
}
}
</script>
I'm not sure what {{currentPlayer}}
specifically has to do with it, but any time you modify the component's state and the view doesn't update, then (assuming there is no error during rendering) it usually means either:
This is a red flag:
this.boardSlots[i] = [];
Vue cannot detect assignments to elements of an array like that (read Array Change Detection). You need to use splice()
or push()
for Vue to know about it. Or alternatively you can construct the boardSlots
array in a local variable and then assign it to this.boardSlots
at the end:
const boardSlots = [];
// Initialize boardSlots ...
this.boardSlots = boardSlots;
Also you're rendering the rows and slots in a weird way; you shouldn't be mutating any state during rendering, local or otherwise (--i
). Just do this:
<div class="board-row" v-for="slots of boardSlots">
<div class="board-slot"
v-for="slot of slots"
:class="[{checked: (slot.owner != 0)}, 'ownedBy-player-' + slot.owner]"
@click="checkSlot(slot.row, slot.col)">
</div>
</div>
But this may not have anything to do with your reactivity issue.