Vue3 animation and source code analysis

Keywords: css3 Vue Vue.js

Vue3 animation and source code analysis

1. How does Vue implement animation

In Vue, animation is mainly displayed through the built-in component < transition > < / transition > provided by Vue.

2. Use

1. Wrap a single element or component

<template>
  <div>
      <button @click="isShow = !isShow">toggle</button>
      <transition name="ydkd">
        <h1 v-if="isShow">Content</h1>
      </transition>
  </div>
</template>

<script setup>
import { ref } from '@vue/reactivity';

const isShow = ref(true)
</script>

<style scoped>
.ydkd-enter-from,
.ydkd-leave-to {
  opacity: 0;
}

.ydkd-enter-to,
.ydkd-leave-from {
  opacity: 1;
}

.ydkd-enter-active,
.ydkd-leave-active {
  transition: all 2s ease;
}
</style>

2. Wrap multiple elements or components

<template>
    <div class="container">
        <div>
            <button @click="isShow = !isShow">toggle</button>
        </div>
        <transition name="ydkd" mode="out-in" :appear="true">
            <h1 class="tip" v-if="isShow">Hello transition</h1>
            <h1 class="tip" v-else>Hello YDKD</h1>
        </transition>
    </div>
</template>

<script setup>
import { ref } from '@vue/reactivity';

const isShow = ref(true);


</script>

<style scoped>
.container {
    margin: 0 auto;
    text-align: center;
}
.tip {
    display: inline-block;
}
.ydkd-enter-active {
    animation: bounce 2s ease;
}
.ydkd-leave-active {
    animation: bounce 2s ease reverse;
}

@keyframes bounce {
    0% {
        transform: scale(0);
    }

    50% {
        transform: scale(1.2);
    }

    100% {
        transform: scale(1);
    }
}
</style>

Details:

  • When multiple components are switched, two components will be displayed at the same time. You can set the mode attribute for < transition mode = "out in" > < / transition >, with two values.
    • out-in first disappears the current, and then introduces the subsequent
    • in-out first enters the subsequent, and then disappears the current
  • At the beginning of the page, the user may see the animation, and can give < transition: appearance = "true" > < / transition >, that is, the animation is turned on by default, and the attribute value of appearance is false by default
    • In fact, the appear ance attribute is the value of the [name] - enter active attribute of the element. Can be in Source code analysis See in.

3. class of transition animation

V-enter-from - > v-enter-to from hidden to displayed
V-leave-to < - v-leave-from show to hide
V-enter-active < - > v-leave-active transition animation effect from element display to hide / from hide to display

graphic

4. Implementation principle

When Vue finds elements wrapped by < transition > < / transition > during template compilation, Vue will perform the following processing

  • 1. Automatically sniff whether CSS transition or animation is applied to the target element. If so, add / delete CSS class names at the appropriate time
  • 2. If the transition component provides JavaScript hook functions, these hook functions will be called at the right time;
  • 3. If no JavaScript hook is found and no CSS transition / animation is detected, DOM insertion and deletion will be performed immediately

5. Source code analysis

1. The persistent attribute is true and marked as < transition > < / transition >, which means that the insert/remove element will not be performed at present and will be skipped at the render layer.
2. For < transition name = "ydkd" > < / transition >, if name is not set, v will be taken in the source code.

const {
    name = 'v',
    type,
    duration,
    enterFromClass = `${name}-enter-from`,
    enterActiveClass = `${name}-enter-active`,
    enterToClass = `${name}-enter-to`,
    appearFromClass = enterFromClass,
    appearActiveClass = enterActiveClass,
    appearToClass = enterToClass,
    leaveFromClass = `${name}-leave-from`,
    leaveActiveClass = `${name}-leave-active`,
    leaveToClass = `${name}-leave-to`
  } = rawProps

3. The < transition > < / transition > component contains many hook functions. When judging the display and hiding of elements, such as the first point of the implementation principle, add / delete CSS class names at the right time. The following functions will be used in the source code.

// Add class name
export function addTransitionClass(el: Element, cls: string) {
  cls.split(/\s+/).forEach(c => c && el.classList.add(c))
  ;(
    (el as ElementWithTransition)._vtc ||
    ((el as ElementWithTransition)._vtc = new Set())
  ).add(cls)
}

// Remove class name
export function removeTransitionClass(el: Element, cls: string) {
  cls.split(/\s+/).forEach(c => c && el.classList.remove(c))
  const { _vtc } = el as ElementWithTransition
  if (_vtc) {
    _vtc.delete(cls)
    if (!_vtc!.size) {
      ;(el as ElementWithTransition)._vtc = undefined
    }
  }
}

Posted by garmann on Fri, 12 Nov 2021 10:39:47 -0800