I would like to get into VueJs development and created a simple Minesweeper game.The two dimensional grid is managed by a Vuex state. When clicking on a cell I would like to reveal it so my current code is
[MutationTypes.REVEAL_CELL]: (state, { rowIndex, columnIndex }) => {
state.board[rowIndex][columnIndex].isRevealed = true;
}
Unfortunately this has no affect to the UI. This problem is known and described here
https://v2.vuejs.org/v2/guide/list.html#Caveats
The docs told me to use something like this
import Vue from "vue";
[MutationTypes.REVEAL_CELL]: (state, { rowIndex, columnIndex }) => {
const updatedCell = state.board[rowIndex][columnIndex];
updatedCell.isRevealed = true;
Vue.set(state.board[rowIndex], columnIndex, updatedCell);
Vue.set(state.board, rowIndex, state.board[rowIndex]);
}
but it did not help. Lastly I tried to create a copy of the board, modify the values and assign that copy to the board.
[MutationTypes.REVEAL_CELL]: (state, { rowIndex, columnIndex }) => {
const newBoard = state.board.map((row, mapRowIndex) => {
return row.map((cell, cellIndex) => {
if (mapRowIndex === rowIndex && cellIndex === columnIndex) {
cell = { ...cell, isRevealed: true };
}
return cell;
});
});
state.board = newBoard;
}
This didn't work neither. Does someone got an idea?
I created a Codesandbox showing my project
https://codesandbox.io/s/vuetify-vuex-and-vuerouter-d4q2b
but I think the only relevant file is /store/gameBoard/mutations.js and the function REVEAL_CELL
The problem is in Cell.vue
and the issue is that you're checking an unchanging variable to determine the state of reveal. You've abstracted this.cell.isRevealed
into a variable called isUnrevealed
which is never told how to change after the initial load.
Option 1
isUnrevealed
seems like an unnecessary convenience variable. If you get rid of isUnrevealed
and change the references to it to !cell.isRevealed
, the code will work as expected.
Option 2
If you're set on using this variable, change it to a computed so that it constantly updates itself whenever the Vuex state propagates a change to the cell
isRevealed
prop:
computed: {
isUnrevealed() {
return !this.cell.isRevealed;
}
}
If you go this route, don't forget to remove the property from data
and remove the assignment in mounted
(first line).
You'll also have the same problem with isMine
and cellStyle
. So, completely remove data
and mounted
and make them both computed as well.
computed: {
isMine() {
return this.cell.isMine;
},
cellStyle() {
if (!this.cell.isRevealed) {
return "unrevealedCell";
} else {
if (this.isMine) {
return "mineCell";
} else {
let neighbourCountStyle = "";
... // Switch statement
return `neutralCell ${neighbourCountStyle}`;
}
}
}
}