Vue: TransitionGroup
2022-04-01
0. Intro
<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:
- By default, it doesn’t render a wrapper element. But you can specify an element to be rendered with the
tag
prop. - 没有 wrapper element - Transition modes are not available, because we are no longer alternating between mutually exclusive elements.
- Elements inside are always required to have a unique
key
attribute. - CSS transition classes will be applied to individual elements in the list, not to the group / container itself.
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
})
}