Как задать класс по клику во VueJS

Есть вот такой код:

<div class="game__wrapper">
    <div v-for="(_, x) in 3" :key="x" class="row">
        <button v-for="(_, y) in 3" :key="y" class="square" @click="move(x, y)">
            {{ squares[x][y] }}
        </button>
    </div>
</div>

сама функция

const move = (x, y) => {
    if (winner.value) return
    squares.value[x][y] = player.value
    player.value = player.value === 'O' ? 'X' : 'O'
}

Создается 9 кнопок, мне нужно, чтоб при нажатии на какую-то к этой кнопке добавлялся класс 'square--lock' Просидел весь день, ничего не придумал. Спасибо за помощь!) UPD: использую Vue Composition API


Ответы (2 шт):

Автор решения: zflexz

Спустя 2 дня, я всё-таки нашел способ. Да, он костыльный, я уверен, что можно сделать что-то лучше, но:

let squaresArr = squares.value.flat()
let domSquares = document.querySelectorAll('.square')
for (let i = 0; i < squaresArr.length; i++) {
    if(squaresArr[i] !== ''){
        domSquares[i].classList.add('squareLock')
    }               
}

Этот код я добавил в функцию move. Таким образом, в переменной squaresArr хранится массив со значениями всех 9-ти кнопок. Перебирая массив мы получаем индексы тех кнопок, которые ещё не нажаты. Также была создана переменная domSquares , хранящая массив этих же кнопок, но уже из DOM дерева. В итоге, элемент в domSquares с этим индексом нам и нужен.

→ Ссылка
Автор решения: Дмытрык

 const app = new Vue({
el: "#app",
data() {
  return {
    table: [
      [
        0, 0, 0
      ],
      [
        0, 0, 0
      ],
      [
        0, 0, 0
      ],

    ],
    activeIndex: {
        x: -1,
        y: -1
    }
  };
},
methods: {
  tableClick(x, y) {
    this.activeIndex.x = x
    this.activeIndex.y = y

  },
},
  });
.row {
  width: 30px;
  height: 30px;
  border: 1px solid;
}

.table {
  display: flex;
}

.active {
  background: red
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>


<div id="app">
    <div class="table">
        <div class="column" v-for="(row, x) in table">
            <div class="row" v-for="(value, y) in row" :class="activeIndex.x === x && activeIndex.y === y ? 'active': ''"
                 @click="tableClick(x,y)" :key="x+''+y">
            </div>
        </div>
    </div>
</div>

Если Вам надо только добавить класс, то можно так:

 const app = new Vue({
el: "#app",
data() {
  return {
    table: [
      [
        0, 0, 0
      ],
      [
        0, 0, 0
      ],
      [
        0, 0, 0
      ],

    ],
  };
},
methods: {
  tableClick(event) {
event.target.classList.add('active')
  },
},
  });
.row {
  width: 30px;
  height: 30px;
  border: 1px solid;
}

.table {
  display: flex;
}

.active {
  background: red
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>


<div id="app">
    <div class="table">
        <div class="column" v-for="(row, x) in table">
            <div class="row" v-for="(value, y) in row" 
                 @click="tableClick(x, y)" :key="x+''+y">
            </div>
        </div>
    </div>
</div>

Или так

 const app = new Vue({
el: "#app",
data() {
  return {
    table: [
      [
        0, 0, 0
      ],
      [
        0, 0, 0
      ],
      [
        0, 0, 0
      ],

    ],
  };
},
methods: {
  tableClick(row, y) {
    row.splice(y,1,1) // splice - для реактивности, но во Vue3, наверное, не будет этой проблемы
 },
},
  });
.row {
  width: 30px;
  height: 30px;
  border: 1px solid;
}

.table {
  display: flex;
}

.active {
  background: red
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>


<div id="app">
    <div class="table">
        <div class="column" v-for="(row, x) in table">
            <div class="row" v-for="(value, y) in row" :class="value ? 'active': ''"
                 @click="tableClick(row,y)" :key="x+''+y">
            </div>
        </div>
    </div>
</div>

→ Ссылка