shake_shake1
@shake_shake1
HTML-программист, 1С-разработчик, чиню утюги.

Почему transition-group не работает?

Есть меню - рендерится из массива объектов в $el.data
При клике у всех элементов убирается флаг isActive, потом массив фильтруется (это делал специально, т.к. думал, что при сортировке может не быть анимации), и дальше удаленный элемент со флагом isActive вставляется в начало массива.
Но анимация работает только если менять существующие значения свойств этого элемента. В чём здесь может быть загвоздка?
Делал всё, как написано в доке (и со splice по индексу заменять пробовал) - работает только один вариант.
template

<template>
  <v-toolbar dense color="#195d6a">
    <transition-group name="list" tag="div" class="toolbar-wrapper">
      <p v-for='comp in links'
            :key="comp.name"
            :class="{'selected': comp.isActive}"
            @click="setActive(comp)">
            <router-link :to="comp.name" :key="comp.name">
            {{comp.text}}
            </router-link>
      </p>
    </transition-group>
  </v-toolbar>
</template>

data, methods

data() {
      return {
        links: [
          { name: '/dashboard', text: 'Панель управления', isActive: true },
          { name: '/table', text: 'Таблица', isActive: false },
          { name: '/ratesSetter', text: 'Тарифы', isActive: false },
          { name: '/chart', text: 'График', isActive: false },
          { name: '/logsBook', text: 'Журнал', isActive: false },
        ],
      }
    },
    methods: {
      setActive(comp) {
        let clicked;
        // Удаляем isActive: true у предыдущего активного элемента
        this.links = this.links.map(it => {
          return it.name === comp.name ? {...it, isActive: true} : {...it, isActive: false}
        });
        // Удаляем элемент
        this.links = this.links.filter(it => {
          if (it.name !== comp.name) {
            return true;
          } else clicked = it
        });

        // И вставляем в начало

        /* this.links.unshift(clicked) */ // Так анимация не работает
        /* this.links = [clicked, ...this.links]*/ // Так тоже

        // this.links = [                           // Не работает
        //   {
        //     ...clicked,
        //     toMakeAnimWork: Math.random()
        //   },
        //   ...this.links
        // ];

        // this.links.unshift({                    // И так ничего не работает
        //   text: clicked.text,
        //   name: clicked.name,
        //   isActive: clicked.isActive});


        //А вот так работает
        this.links.unshift({
          text: clicked.text,
          name: clicked.name + 'fff',
          isActive: clicked.isActive
        });
      },



css

.list-enter-active, .list-leave-active {
    transition: all .5s;
  }
  .list-enter, .list-leave-to {
    opacity: 0;
    transform: translateY(-50px);
  }
  .v-toolbar {
    font-family: Montserrat, Arial, sans-serif;
    font-size: 1.2rem;
  }
  .toolbar-wrapper {
    display: flex;
  }
  a {
    text-decoration: none;
    color: #95d9e5;
    transition: background-color .2s;
    padding: 13px 18px;
  }
  a:hover {
    color: #fff;
    background: #30b0c7;
  }
  p.selected a {
    color: rgba(255,255,255, .5);
  }
  • Вопрос задан
  • 822 просмотра
Решения вопроса 1
Если поменяете :key="comp.name" на :key="comp.isActive", то заработает.
Ключи vue использует для сопоставления данных и dom элементов из которых они генерируются. Поэтому анимации не знают момент перерисовки и не запускается
Можно составные ключи делать:
:key="comp.name + comp.isActive "
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
0xD34F
@0xD34F Куратор тега Vue.js
С помощью классов *-enter-active, *-leave-active и т.д. анимируются удаляемые/добавляемые элементы. Если key не изменился, элемент не будет удалён и заново добавлен, соответственно, и классы не будут добавляться.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы