Enter/Leave & List transition

Vue provides a variety of different application transitions when inserting, updating, or removing the DOM. The following tools are included:

  • Automatically apply classes in CSS transitions and animations
  • You can use third-party CSS animation libraries such as Animate. CSS
  • Use JavaScript to manipulate the DOM directly in the transition hook function
  • You can use third-party JavaScript animation libraries such as Velocity.js

Here, I’m just talking about transitions in, out, and to lists

Single-element component transitions

Vue provides the components that encapsulate the transition. You can add an in/out transition to any element or component in the following situations

  • Conditional rendering (usingv-if )
  • Conditional display (usev-show )
  • Dynamic components
  • Component root node

Class name for transition & CSS transition

When inserting or removing an element contained in the Transition tag, the element is animated by adding and removing the six class names entering/leaving the element

  1. v-enter: Defines the initial state the element enters
  2. v-enter-active: Defines the element to enter the transition animationtransition
  3. v-enter-to: Defines the state the element enters at the end of the animation
  4. v-leave: Defines the initial state in which an element leaves
  5. v-leave-active: Defines the element to leave the transition animationtransition
  6. v-leave-to: Defines the state of the element when it leaves the end of the animation
  • The top provides the state of the element at four points in time, if the transition of the element isWhere did you come from? Back to whereEnter the pre-statePost-departure stateThe same,After statePre-departure stateSame, so the CSS can be written together
.v-enter,.v-leave-to{// the state of the element before entering and at the end of leaving //... }.v-enter-to,.v-leave{// This set of CSS will be removed after the transition, immediately restore, no transition animation //... // So in order to have a transition, the element itself needs to have a transition animation to restore the original style}Copy the code
  • v-enter-activev-leave-activeUsed to define entering and leaving an animationtransitionAnd the same thing can be written together
.v-enter-active,.v-leave-active{
    //...
}
Copy the code

Use the
tag to wrap the elements that need to be transitioned, and v- is the default prefix for these class names. Write the name attribute inside the tag and name it
, so the V-Enter is written as my-transition-Enter to customize the transition animation separately for this type of element

CSS animations

CSS animation usage is the same as CSS transition, the difference is that the V-Enter class name is not deleted immediately during the animation, but is deleted at the end of the animation

<div>
  <button @click="show = ! show">Toggle show</button>
  <transition>
    <p v-if="show">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
  </transition>
</div>
Copy the code
new Vue({
  data: {
    show: true}})Copy the code
.v-enter-active {
  animation: bounce-in .5s;
}
.v-leave-active {
  animation: bounce-in .5s reverse;
}
@keyframes bounce-in {
  0% {
    transform: scale(0); 50%} {transform: scale(1.5); 100%} {transform: scale(1); }}Copy the code

Custom transition class name

  • enter-class
  • enter-active-class
  • enter-to-class
  • leave-class
  • leave-active-class
  • leave-to-class

They take precedence over normal class names, which is useful for Vue’s transition system in combination with other third-party CSS animation libraries, such as Animate.

<link href="https://cdn.jsdelivr.net/npm/[email protected]" rel="stylesheet" type="text/css">

<div>
  <button @click="show = ! show">
    Toggle render
  </button>
  <transition
    name="custom-classes-transition"
    enter-active-class="animated tada"
    leave-active-class="animated bounceOutRight"
  >
    <p v-if="show">hello</p>
  </transition>
</div>
Copy the code
new Vue({
  data: {
    show: true}})Copy the code

Use transitions & animations as well

Vue provides event listeners for both transitionEnd and Animationend. Vue automatically identifies the type and sets the listener

However, in some scenes, it is necessary to have two transitions on the same element at the same time. For example, the animation is triggered and completed quickly, but the transition is not finished. In this case, you need to explicitly declare the type you want Vue to listen on by using the Type property and setting the animation or Transition

The duration of the dominant transition

You can customize an explicit transition duration (in milliseconds) using the duration Prop on the < Transition > component:

<transition :duration="1000">.</transition>
Copy the code

You can also customize the duration of entry and removal:

<transition :duration="{ enter: 500, leave: 800 }">.</transition>
Copy the code

JavaScript hooks

You can declare JavaScript hooks in an attribute

<transition
  v-on:before-enter="beforeEnter"
  v-on:enter="enter"
  v-on:after-enter="afterEnter"
  v-on:enter-cancelled="enterCancelled"

  v-on:before-leave="beforeLeave"
  v-on:leave="leave"
  v-on:after-leave="afterLeave"
  v-on:leave-cancelled="leaveCancelled"
>
  <! -... -->
</transition>
Copy the code
// ...
methods: {
  // --------
  / / to enter
  // --------

  beforeEnter: function (el) {
    // ...
  },
  // When used in conjunction with CSS
  // The done callback is optional
  enter: function (el, done) {
    // ...
    done()
  },
  afterEnter: function (el) {
    // ...
  },
  enterCancelled: function (el) {
    // ...
  },

  // --------
  / / when they leave
  // --------

  beforeLeave: function (el) {
    // ...
  },
  // When used in conjunction with CSS
  // The done callback is optional
  leave: function (el, done) {
    // ...
    done()
  },
  afterLeave: function (el) {
    // ...
  },
  LeaveCancelled only for v-shows
  leaveCancelled: function (el) {
    // ...}}Copy the code

These hook functions can be used with CSS Transitions /animations or on their own

When using JavaScript transitions only, the done callback must be used in Enter and leave; otherwise, they are called synchronously and the transition completes immediately

It is recommended to add v-bind: CSS =”false” for elements that are transitioning only using JavaScript. Vue will skip the CSS detection, which can also avoid CSS influence during the transition

Transition of multiple elements

A single node, one of several nodes rendered at the same time, can be used v-if/ V-else for native tags, the most common multi-label transition is a list and an element describing the list as an empty message:

<transition>
  <table v-if="items.length > 0">
    <! -... -->
  </table>
  <p v-else>Sorry, no items found.</p>
</transition>
Copy the code

You can use it this way, but with one caveat:

When elements with the same tag name are switched, they need to be marked with a unique value set by the key attribute for Vue to distinguish them, otherwise Vue will only replace the contents inside the same tag for efficiency, even if it is not technically necessary. It is a better practice to set keys for multiple elements in the < Transition > component

Example:

<transition>
  <button v-if="isEditing" key="save">
    Save
  </button>
  <button v-else key="edit">
    Edit
  </button>
</transition>
Copy the code

In some scenarios, it is also possible to replace v-if and V-else by giving different states to the key attribute of the same element. The above example can be rewritten as:

<transition>
  <button v-bind:key="isEditing">
    {{ isEditing ? 'Save' : 'Edit' }}
  </button>
</transition>
Copy the code

A multi-element transition with multiple V-ifs can be rewritten as a single-element transition with a dynamic property bound. Such as:

<transition>
  <button v-if="docState === 'saved'" key="saved">
    Edit
  </button>
  <button v-if="docState === 'edited'" key="edited">
    Save
  </button>
  <button v-if="docState === 'editing'" key="editing">
    Cancel
  </button>
</transition>
Copy the code

It can be rewritten as:

<transition>
  <button v-bind:key="docState">
    {{ buttonMessage }}
  </button>
</transition>
Copy the code
computed: {
  buttonMessage: function () {
    switch (this.docState) {
      case 'saved': return 'Edit'
      case 'edited': return 'Save'
      case 'editing': return 'Cancel'}}}Copy the code

Transition mode

Switching between multiple elements, entering and leaving at the same time, is the default behavior for < Transition >, and Vue provides the transition mode

  • out-in: When the current element leaves, a new element enters
  • in-outThe new element enters first and the current element leaves when it is finished. This pattern is not commonly used, but provides a possibility
<transition name="fade" mode="out-in">
  <! -... the buttons ... -->
</transition>
Copy the code

Multiple component transitions

The transition between multiple components is much easier – we don’t need to use key attributes, instead, we just need to use dynamic components:

<transition name="component-fade" mode="out-in">
  <component v-bind:is="view"></component>
</transition>
Copy the code
new Vue({
  el: '#transition-components-demo'.data: {
    view: 'v-a'
  },
  components: {
    'v-a': {
      template: '<div>Component A</div>'
    },
    'v-b': {
      template: '<div>Component B</div>'}}})Copy the code
.component-fade-enter-active..component-fade-leave-active {
  transition: opacity .3s ease;
}
.component-fade-enter..component-fade-leave-to{
  opacity: 0;
}
Copy the code

List the transition

Render the entire list at the same time, such as with v-for. In this scenario, use the
component.

  • Different from the<transition>, it will be presented as a real element: the default is one<span>, can also passtagAttribute to another element
  • The transition mode is not available because we no longer switch between unique elements
  • Internal elementsAlways need toProvide uniquekeyAttribute values
  • CSS transition classes will be applied to internal elements, not to the group/container itself

List entry/exit transition

<transition-group name="list" tag="p">
    <span v-for="item in items" v-bind:key="item" class="list-item">
      {{ item }}
    </span>
</transition-group>
Copy the code

When adding and removing elements, surrounding elements will teleport to their new layout instead of a smooth transition, which will be addressed below

Sort the list transition

A special feature of < Transition-Group > components is that they can not only enter and leave an animation, but also change its orientation. The V-Move class is applied to elements when they change their orientation, using transforms to transform them smoothly from their previous position, just like the previous class name. You can customize the prefix with the value of the name attribute or manually set it with the move-class attribute

The element cannot be set to display: inline. Instead, it can be set to display: If the element is removed from the v-move, add an absolute position to the v-leave-active element to resolve the issue that there is no animation after the element is removed from the V-move. If the absolute position causes the element width to be abnormal, see the situation

.v-move {
	transition: 0.3 s ease-in-out;
}
.v-leave-active { 
	position: absolute;
	height: 100%;
}
Copy the code

Reusable transitions

Transitions can be reused through Vue’s component system. To create a reusable transition component, place either
or
as the root component and place any child components in it

Vue.component('my-special-transition', {
  template: ` 
       `.methods: {
    beforeEnter: function (el) {
      // ...
    },
    afterEnter: function (el) {
      // ...}}})Copy the code

Dynamic transition

Even transitions are data-driven in Vue, and the most basic example of a dynamic transition is binding dynamic values via a name attribute

<transition v-bind:name="transitionName">
  <! -... -->
</transition>
Copy the code

This is useful when you want to use Vue’s transition system to define CSS transitions/animations to switch between transitions

All transition attributes can be dynamically bound, but not only attributes can be leveraged, but all data in the context can be retrieved through event hooks, which are methods, meaning that JavaScript transitions can behave differently depending on the state of the component

<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>

<div id="dynamic-fade-demo" class="demo">
  Fade In: <input type="range" v-model="fadeInDuration" min="0" v-bind:max="maxFadeDuration">
  Fade Out: <input type="range" v-model="fadeOutDuration" min="0" v-bind:max="maxFadeDuration">
  <transition
    v-bind:css="false"
    v-on:before-enter="beforeEnter"
    v-on:enter="enter"
    v-on:leave="leave"
  >
    <p v-if="show">hello</p>
  </transition>
  <button
    v-if="stop"
    v-on:click="stop = false; show = false"
  >Start animating</button>
  <button
    v-else
    v-on:click="stop = true"
  >Stop it!</button>
</div>
Copy the code
new Vue({
  el: '#dynamic-fade-demo'.data: {
    show: true.fadeInDuration: 1000.fadeOutDuration: 1000.maxFadeDuration: 1500.stop: true
  },
  mounted: function () {
    this.show = false
  },
  methods: {
    beforeEnter: function (el) {
      el.style.opacity = 0
    },
    enter: function (el, done) {
      var vm = this
      Velocity(el,
        { opacity: 1 },
        {
          duration: this.fadeInDuration,
          complete: function () {
            done()
            if(! vm.stop) vm.show =false}})},leave: function (el, done) {
      var vm = this
      Velocity(el,
        { opacity: 0 },
        {
          duration: this.fadeOutDuration,
          complete: function () {
            done()
            vm.show = true}})Copy the code

Finally, the final solution for creating dynamic transitions is for components to dynamically modify the previous transitions by accepting props. As the old saying goes, the only limit is your imagination.