Luna Tech

Tutorials For Dummies.

Vue: TransitionGroup

2022-04-01


0. Intro

TransitionGroup | Vue.js (vuejs.org) API reference

<TransitionGroup> is a built-in component designed for animating the insertion, removal, and order change of elements or components that are rendered in a list.

When used in DOM templates , it should be referenced as <transition-group>.


1. 与 <Transition> 的区别

<TransitionGroup> supports the same props, CSS transition classes, and JavaScript hook listeners as <Transition>, with the following differences:


2. Enter / Leave Transitions

Example

Here is an example of applying enter / leave transitions to a v-for list using <TransitionGroup>.

<TransitionGroup name="list" tag="ul">
  <li v-for="item in items" :key="item">
    {{ item }}
  </li>
</TransitionGroup>
.list-enter-active,
.list-leave-active {
  transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}

3. Move Transitions

上面那个例子的问题是,在 element 被插入或移除的时候,它边上的其他 element 会跳到新的位置,没有过渡,我们可以加一些过渡的 CSS。

.list-move, /* apply transition to moving elements */
.list-enter-active,
.list-leave-active {
  transition: all 0.5s ease;
}

.list-enter-from,
.list-leave-to {
  opacity: 0;
  transform: translateX(30px);
}

/* ensure leaving items are taken out of layout flow so that moving
   animations can be calculated correctly. */
.list-leave-active {
  position: absolute;
}

4. Staggering List Transitions

通过 data attribute 和 JS transition 来 communicate,使得我们可以在 list 里面 stagger transitions。

首先,我们 render the index of an item as a data attribute on the DOM element。

<TransitionGroup
  tag="ul"
  :css="false"
  @before-enter="onBeforeEnter"
  @enter="onEnter"
  @leave="onLeave"
>
  <li
    v-for="(item, index) in computedList"
    :key="item.msg"
    :data-index="index"
  >
    {{ item.msg }}
  </li>
</TransitionGroup>

然后在 JS hook 里面,我们根据 data attribute 给 animation 加一个 delay。

function onEnter(el, done) {
  gsap.to(el, {
    opacity: 1,
    height: '1.6em',
    delay: el.dataset.index * 0.15,
    onComplete: done
  })
}