Невозможно изменить переход на лету для группы переходов

#vue.js #vue-transitions

Вопрос:

В моем приложении нажатие кнопки закрытия модала заставляет его исчезать с анимацией затухания, в то время как прокрутка вниз заставляет его исчезать с анимацией свайпа. Это делается путем изменения модальности <transition name> в зависимости от события.

То же самое, похоже, не работает с переходной группой. Я делаю что-то не так, или это на самом деле невозможно?

CodeSandbox

Шаблон:

 <transition-group :name="itemTransition">
  <div
    v-for="item in items"
    :key="item.id"
    v-hammer:swipe.up="() => onSwipeUp(notification.id)"
  >
  </div>
</transition-group>
 

Скрипт:

 export default {
  data () {
    return {
      applySwipeTransition: false
    }
  },
  computed: {
    itemTransition () {
      return this.applySwipeTransition ? 'swipe' : 'fade'
    }
  },
  methods: {
    onSwipeUp (id) {
      this.applySwipeTransition = true
      this.$nextTick(() => {
        this.closeItem(id)
        this.applySwipeTransition = false
      })
    }
  }
}
 

CSS:

 .fade-leave-active {
  animation: fade-out .75s;
}

.swipe-leave-active {
  animation: slide-up .25s;
}
 

Ответ №1:

Проблема заключается в сроках обновления компонентов. Вы переключаете режим перехода обратно fade в тот же цикл обновления, что и при закрытии элемента. Таким образом, когда запускается следующее обновление компонента (путем удаления элемента), переход уже переключается обратно fade . На данный момент вы, возможно, догадались, что все, что нужно сделать, — это переключить переход обратно в следующем обновлении, вызванном удалением элемента:

    onSwipeUp (id) {
     this.applySwipeTransition = true
     this.$nextTick(() => {
        this.closeItem(id)
        this.$nextTick(()=>{
          this.applySwipeTransition = false
        })         
     })
   }
 

Поскольку нет причин ждать обновления компонента, чтобы закрыть элемент, вы можете немного упростить код:

    onSwipeUp (id) {
      this.applySwipeTransition = true
      this.closeItem(id)
      this.$nextTick(() => {
        this.applySwipeTransition = false
      })
    }
 

Вот ваша рабочая песочница: https://codesandbox.io/s/vue-template-forked-60lkk?file=/src/App.vue

Комментарии:

1. Работает, спасибо! ТАК что не позволяйте мне назначать награду сейчас, придется ждать 4 часа. Один вопрос, однако, в моей песочнице я на самом деле (1) установил переход на свайп, (2) удалил элемент в следующем цикле обновления, (3) вернул переход на затухание в следующем цикле обновления. Почему это не работает? Я понимаю, что нет необходимости делать что-то в таком количестве последовательных циклов обновления, но это все равно должно работать, так как каждый шаг выполняется в хронологическом порядке циклов обновления, не так ли?

2. в вашем коде оба вызова nextTick () (для удаления элемента и переключения перехода) выполняются синхронно, поэтому при регистрации они оба ожидают одного и того же цикла обновления. чтобы быть последовательным, следующая функция nextTick() должна быть вызвана из предыдущего цикла обновления. вот почему вы должны их гнездить. думайте о них как о вызовах асинхронных функций. не уверен, что я хорошо объяснил, должен признать, что их сложно понять

3. Нет, я вроде как понимаю тебя, спасибо за разъяснение 🙂

Ответ №2:

Итак, я поработал с вашим CSS, вручную изменив name <transition-group его на » или fade «или swipe «, чтобы посмотреть, есть ли проблемы с анимацией CSS.

Вердикт: fade Работает. swipe только переходы list-item со страницы с помощью щелчка и перетаскивания, а не истинного свайпа, если это вас касается (кстати, мой свайп-это свайп macOS двумя пальцами, без щелчка).

До сих пор, не изменяя при этом сайт CodePen, проблема, кажется, с вашей computed отель, где нет ничего рассказывать name , чтобы изменить динамически, даже если вы связали ее в computed собственность — логика itemTransition() , кажется, всегда по умолчанию fade , потому что applySwipeTransition никогда не равно «проведите пальцем», учитывая, что CSS не работает, когда вы вручную изменить name на swipe (см. «приговор)».

Чтобы понять, в чем заключалась основная проблема, я поработал с вашим itemTransition() :

 computed: {
    itemTransition() {
      return this.applySwipeTransition ? "fade" : "swipe";
    },
 

Переключение порядка fade и swipe теперь делает swipe работу. Я надеюсь, что это даст вам некоторое представление об этой проблеме. Возможно, вам потребуется создать пользовательскую директиву или событие Vue для обработки логики свайпа / затухания, если это необходимо.