Vue based transition requires that you have a prior knowledge of transition and transition-group for VUE.

transition

The VUE documentation provides a detailed analysis of the Transtion component.

Here is my understanding:

Transtion is an abstract component provided by VUE that helps us manipulate its wrapped child elements when appropriate.

The right time is:

  1. beforeEnterThe DOM is generated from JS and inserted into the page in the frame (corresponding to the animation below).
  2. enterThe next frame after the DOM is inserted into the page (corresponding to the animation below)
  3. afterEnterThe next frame after the DOM animation is complete (corresponding to the end of the animation below)

The concept of frames is mentioned several times, and I talked about it in the last article, if you’re interested

Juejin. Cn/post / 684490…

transition-group

The ransition-group component performs transtion component operations on each element in the list of packages in batches.

html
<div id="app"  @click="num === 0 ? num++ : num = 5">
    <transition-group name="list">
        <item v-for="n in num" :key=n />
    </transition-group>
</div>
Copy the code
css
.list-enter {
    opacity: 0;
    transform: translateY(100%);
}
.list-enter-active {
    transition:.3s;
}
Opacity: 1; /* Opacity: 1; transform: none; * /
.list-enter-to {
    opacity: 1;
    transform: translateY(0);
}
Copy the code

Then add a different delay for each list item.

transition-delay

css
.list-enter-active:nth-child(5n+2) {
    transition-delay:.3s;
}
.list-enter-active:nth-child(5n+3) {
    transition-delay:.5s;
}
.list-enter-active:nth-child(5n+4) {
    transition-delay:.7s;
}
.list-enter-active:nth-child(5n+5) {
    transition-delay:.9s;
}
Copy the code

With transition-delay and CSS selectors, you can indeed achieve interleaved transitions.

But the disadvantages are also obvious, to write a lot of CSS, it is not flexible to modify.

Next we use vue’s JavaScript hooks.

setTimeout

html
<div id="app"  @click="num === 0 ? num++ : num = 5">
    <! -- Add v-bind: CSS ="false" to let vue skip checking CSS and give us more control over when the animation is done -->
    <transition-group 
        v-bind:css="false"
        v-on:before-enter="beforeEnter" 
        v-on:enter="enter"
        v-on:after-enter="afterEnter">

        <item v-for="(n,index) in num" :key=n :data-delay=index*100 />

    </transition-group>
</div>
Copy the code

When transitioning only with JavaScript, you must use done for callbacks in enter and leave. Otherwise, they will be called synchronously and the transition will complete immediately.

new Vue({
    el: "#app".data: (a)= > ({
        num: 0
    }),
    methods: {
        // Let's do the same thing vue does for us in beforeEnter Enter afterEnter hook:
        // Add remove class name, listen for transitionEnd event.
        beforeEnter(dom) {
            dom.classList.add('list-enter'.'list-enter-active');
        },
        enter(dom,done) {
            let delay = dom.dataset.delay;
            setTimeout(function () {
                dom.classList.remove('list-enter');
                dom.classList.add('list-enter-to');
                // Listen for the transitionEnd event
                var transitionend = window.ontransitionend ? "transitionend" : "webkitTransitionEnd";
                dom.addEventListener(transitionend, function onEnd() {
                  dom.removeEventListener(transitionend, onEnd);
                  done(); // Call done() to tell vue that the animation is complete to trigger the afterEnter hook
                });
            }, delay)
        },
        afterEnter(dom) {
            dom.classList.remove('list-enter-to'.'list-enter-active'); }}})Copy the code

So far, it works fine, with staggered transitions and no need to write a lot of CSS.

Let’s go back and see we did two things,.list-enter. List-enter to and setTimeout

Tells the browser to transition the list item from opacity 0 translateY(100%) to opacity 1 translateY(0) at different times.

Tells the browser the different states of the element, in addition to the class name,

We can manipulate the DOM directly, write styles inline,

In addition to not writing CSS class names at all,

It can also be more programmatic.

style

html
<div id="app" @click="num ? num++ : num=5">
        <transition-group 
            v-bind:css="false" 
            v-on:before-enter="beforeEnter" 
            v-on:enter="enter"
            v-on:after-enter="afterEnter">

            <item v-for="(n,index) in num" 
                :key=n 
                :data-delay=index*100 
                data-y="100%"
                />

        </transition-group>
    </div>
Copy the code
new Vue({
    el: "#app".data: (a)= > ({
        num: 0
    }),
    methods: {
        beforeEnter(dom) {
            let { x = 0, y = 0, s = 1, opacity = 0 } = dom.dataset;
            dom.style.cssText = `transition: .3s; opacity:${opacity}; transform: scale(${s}) translateX(${x}) translateY(${y}); `;
        },
        enter(dom,done) {
            let delay = dom.dataset.delay;
            setTimeout(function () {
                dom.style.cssText = `transition: .3s; opacity: 1; transform: scale(1) translateX(0) translateY(0); `;
                // Listen for the transitionEnd event
                var transitionend = window.ontransitionend ? "transitionend" : "webkitTransitionEnd";
                dom.addEventListener(transitionend, function onEnd() {
                  dom.removeEventListener(transitionend, onEnd);
                  done(); // Call done() to tell vue that the animation is complete to trigger the afterEnter hook
                });
            }, delay)
        },
        afterEnter(dom) {
            dom.style.cssText = ""; }}})Copy the code

Yes, but since they are on JS, you can only limit your imagination.

html
    <item v-for="(n,index) in num" 
        :key=n 
        :data-delay=index*100 
        :data-x="index%2 === 0 ? '-50%' : '50%'" 
        :data-y="getRandom()+'%'"
        :data-s="Math.random()"
    />
Copy the code
getRandom() {
    var rate = Math.floor(Math.random() * 90 + 10);
    return Math.random() > 0.5 ? rate : - 1 * rate;
}
Copy the code

The resources

Tips for Changing your Interactive animations from “not bad” to “Super Great”

transition