Активная кнопка фильтрации по тегу! Vue.js

Не могу понять как реализовать подсвечивание выбранную кнопку, которая будет делать фильтрацию по списку - тег! Ранее я использовал моковые данные прям в компоненте, и тогда у меня было поле active: true, ну и я менял состояние все прекрасно.

Но сейчас с API получаю список тегов, и из state забираю список в котором есть поля: name, id.

И как же теперь привязыватся к конкретному элементу не пойму(((

<div v-for="item in tagsList" :key="item.id" class="swiper-slide">
          <AppButton
            blog-tag-btn
            class="swiper-slide-btn"
            :blog-tag-btn-active="isActive"
            @click="selectTag(item.id)"
          >
            {{ item.name }}
          </AppButton>
        </div>
data() {
    return {
      slider: null,
      isActive: false,
    }
  },

methods: {
    selectTag(id) {
      this.isActive = !this.isActive
      this.$emit('select-tag', id)
    },
  },

если я сделаю вот так, то будут подсвечивался сразу все кнопки из моего списка, а не конкретная! В этом примере локальная переменная не спасет, а вот нужно какое-то условие, которое будет учитывать уникальность каждой кнопки, а уникальность эту дает id, я когда так уже делал, но вот совсем как обило(


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

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

new Vue({
  el: '#app',
  data() { return {
    tagsList: [],
    isActive: {},
  }},
  methods: {
    selectTag(id) {
      this.$set(this.isActive, id, !this.isActive[id]);
      this.$emit('select-tag', id);
    },
    fetchItems() {
      fetch('https://jsonplaceholder.typicode.com/users')
        .then(r => r.json()).then(data => this.tagsList = data);
    },
  },
  mounted() {
    this.fetchItems();
  },
});
.swiper-slide { display: inline-block; margin: 0.25rem; }
.swiper-slide-btn { padding: 0.25rem 0.5rem; }
.swiper-slide-btn.active { background: #acf; }
<div id="app">
  <div v-for="item in tagsList" :key="item.id" class="swiper-slide">
    <button class="swiper-slide-btn"
      :class="{ active: isActive[item.id] }"
      @click="selectTag(item.id)"
    >
      {{ item.name }}
    </button>
  </div>
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>

На что тут следует обратить внимание:

  1. isActive: {},
    Это свойство должно содержать структуру, а не одиночное булевое значение - ведь переключаемый элемент у нас не один, их несколько. Обычный объект для такой задачи вполне хорошо подходит.

  2. this.$set(this.isActive, id, !this.isActive[id]);
    Присваивание нового состояния флага выполняется через метод $set, потому что Vue не имеет возможности автоматически отслеживать добавление новых свойств в объекты.
    Если просто присваивать this.isActive[id] = !this.isActive[id], то реактивных обновлений не будет, ведь изначально объект isActive пуст, и Vue "не увидит" в нем появлений новых свойств [id].

  3. :class="{ active: isActive[item.id] }"
    Бинд класса здесь имеет очень простую логику - класс active (через который кнопки и стилизуются) добавляется элементу когда isActive[item.id] принимает значение true.
    А что при значении undefined, когда кнопка еще не переключалась? Тоже просто: здесь Vue автоматически приводит undefined к булевому false, и соотв., класс не добавляется - именно то, что нужно.

→ Ссылка