Adding a few transitions or animations to a cold web page can dramatically improve the texture of the page, giving it a smooth, silky look. It is implemented mainly through the TRANSITION and animation in CSS.

It is encapsulated in VUE framework to provide convenient transition usage.

1, Transition component usage

The transition component is most commonly used in business development:

<transition name="slide-fade">
  <p v-if="show"> hello world </p>
</transition>
Copy the code
/* You can set different entry and exit animations */
/* Sets the duration and animation function */
.slide-fade-enter-active {
  transition: all .3s ease;
}
.slide-fade-leave-active {
  transition: all .8s cubic-bezier(1.0.0.5.0.8.1.0);
}
.slide-fade-enter..slide-fade-leave-to
  transform: translateX(10px);
  opacity: 0;
}
Copy the code

In the entry/exit transition, six hooks are triggered and six class switches are performed.

If your Transition component does not have a name attribute, v- is the default prefix for these class names. If you use
then v-Enter will be replaced with my-transition-Enter.

These six class names are customizable and take precedence over normal class names:

<transition name="slide-fade" 
            enter-active-class="custom-enter-active-class"
            leave-active-class="custom-leave-active-class">
  <p v-if="show"> hello world </p>
</transition>
Copy the code
/* CSS section */
.custom-enter-active-class {
  animation: bounce-in .5s;
}
.custom-leave-active-class {
  animation: bounce-in .5s reverse;
}
@keyframes bounce-in {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.5);
  }
  100% {
    transform: scale(1); }}Copy the code

When switching between elements with the same tag name, it is recommended to set keys for multiple elements in the < Transition > component so that vUE can distinguish between them

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

This example can replace v-if with different values for key:

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

Also switch transitions between different components:

<transition name="component-fade" mode="out-in">
  <component :is="view"></component>
</transition>
Copy the code
export default {
  data () {
    return {
    	view: 'v-a'}},components: {
    'v-a': {
      template: '<div>Component A</div>'
    },
    'v-b': {
      template: '<div>Component B</div>'}}}Copy the code

By default, these two components is enter and leave at the same time, a left transition began to shift into another, only to leave the components of the completion of animation, will only let the position, which can cause a caton usually effect (if two elements are set up absolute positioning, there is no this problem).

We can satisfy our needs by adding the transition mode mode:

  • in-out: The new element transitions first, then the current element transitions away.
  • out-in: The current element transitions first, and then the new element transitions in.

In general, we use out-of-in more often, allowing the current element to leave before new elements enter.

<transition name="fade" mode="out-in">
  <! -- Different elements -->
</transition>
Copy the code

Knowing the above usage, you are ready to implement most business scenarios.

2. Use JavaScript for dynamic transitions

For most scenarios, we use CSS primarily for transitions, which are already written up front, but in some cases we also need dynamic transitions.

The most basic operation of dynamic transition is to bind dynamic attributes, such as name, and switch different transition effects in different situations.

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

However, this also requires us to write the corresponding transition effect in advance. Besides, the most direct way to achieve dynamic transition is to use JavaScript transition:

<transition
  @before-enter="beforeEnter"
  @enter="enter"
  @after-enter="afterEnter"
  @enter-cancelled="enterCancelled"

  @before-leave="beforeLeave"
  @leave="leave"
  @after-leave="afterLeave"
  @leave-cancelled="leaveCancelled"
>
  <! -... -->
</transition>
Copy the code
methods: {
  // The transition is triggered before entering
  beforeEnter: function (el) {},// Triggered when transition enters
  enter: function (el, done) {
    // ...
    The done callback is optional when used with CSS
    If CSS ="false", the done callback must be used
    done()
  },
  // Triggered when the transition enters the end
  afterEnter: function (el) {},// Triggered when transition entry is cancelled
  enterCancelled: function (el) {},// Trigger before leaving
  beforeLeave: function (el) {},// Triggered when leaving
  leave: function (el, done) {
    // ...
    When used with CSS, the done callback is optional
    If CSS ="false", the done callback must be used
    done()
  },
  // Triggers after leaving
  afterLeave: function (el) {},// Triggered when the exit process is cancelled (only used in V-show)
  leaveCancelled: function (el) {}}Copy the code

The JavaScript transitions hooks above can be used with CSS Transitions /animations or separately.

However, since you are using JavaScript transitions, it is recommended not to use CSS transitions. Add v-bind: CSS =”false” to the element and Vue will skip the CSS detection. This also avoids the impact of CSS during the transition.

Take this example:

<! -- Velocity works in a similar way to jquery.animate and is a great choice for implementing JavaScript animations.
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>

<div id="example-4">
  <button @click="show = ! show">
    Toggle
  </button>
  <transition
    @before-enter="beforeEnter"
    @enter="enter"
    @leave="leave"
    :css="false"
  >
    <p v-if="show">
      Demo
    </p>
  </transition>
</div>
Copy the code
new Vue({
  el: '#example-4'.data: {
    show: false
  },
  methods: {
    // Write specific transition data in the hook function, can realize JS dynamic control
    beforeEnter: function (el) {
      el.style.opacity = 0
      el.style.transformOrigin = 'left'
    },
    enter: function (el, done) {
      Velocity(el, { opacity: 1.fontSize: '1.4 em' }, { duration: 300 })
      Velocity(el, { fontSize: '1em' }, { complete: done })
    },
    leave: function (el, done) {
      Velocity(el, { translateX: '15px'.rotateZ: '50deg' }, { duration: 600 })
      Velocity(el, { rotateZ: '100deg' }, { loop: 2 })
      Velocity(el, {
        rotateZ: '45deg'.translateY: '30px'.translateX: '30px'.opacity: 0
      }, { complete: done })
    }
  }
})
Copy the code

3, initial render appear

The use of transitions above usually requires changes in elements or components, such as V-if, V-show, dynamic components, etc.

You can use the “Appear” attribute if your request is rendered the first time it comes to the page, and then doesn’t need to be rendered again. Here’s an example:

<! -- Appear can also customize the CSS class name --> 
<transition appear
            appear-class="custom-appear-class"
            appear-active-class="custom-appear-active-class"
            appear-to-class="custom-appear-to-class">
  <p>I'm a test appear initial render text</p>
</transition>
Copy the code
.custom-appear-class{
  opacity: 0;
}
.custom-appear-active-class{
  transition: all 3s;
}
.custom-appear-to-class{
  opacity: 1;
}
Copy the code

“Appear” is a bit like “Enter”, but it only fires during the initial rendering, and you can make a natural transition by setting the state before and after it fires differently.

It can also be implemented using JavaScript hook functions:

<transition appear 
            @before-appear="customBeforeAppearHook"
            @appear="customAppearHook"
            @after-appear="customAfterAppearHook"
            @appear-cancelled="customAppearCancelledHook">
  <! -... -->
</transition>
Copy the code

4. List transitions and V-moves

Use the
component to render a single node or one of multiple nodes at the same time. If you render multiple nodes at the same time, such as an entire list, use the
component. This component has several features:

  • Different from the<transition>, it will be rendered as a real element: the default is one<span>. Can be achieved bytagProperty is replaced with another element.
  • There is no transition mode in the list rendering.
  • Internal elements must be providedkeyValue.
<! -- Set the tag attribute to p element, and set the key value for each item in v-for -->
<! -- items is an array of consecutive numbers [0, 1, 2...]  -->
<transition-group name="list" tag="p" class="list-item">
   <span v-for="item in items" :key="item">
     {{ item }}
   </span>
</transition-group>
Copy the code
.list-item {
  display: inline-block;
  margin-right: 10px;
}
.list-enter-active..list-leave-active {
  transition: all 1s;
}
.list-enter..list-leave-to {
  opacity: 0;
  transform: translateY(30px);
}
Copy the code

It looks like this, but there’s a problem: as you add and remove elements, the surrounding elements will teleport to their new layout position, giving the impression of being stuck.

You can solve this problem by using the V-move class in the
component, which is applied during element change positioning. As with the previous class name, the prefix can be customized using the Name attribute or manually set using move-class attribute.

So just modify the CSS in the above example:

.list-item {
  display: inline-block;
  margin-right: 10px;
}
/* Add a.list-move class style, which takes effect when the element changes */
.list-move{
  transition: all 1s;
}
.list-enter-active..list-leave-active {
  transition: all 1s;
}
/* Add an absolute positioning attribute */ when the element leaves
/* When the element leaves, it triggers a position change to make the above.list-move effective */
/* If there is no absolute positioning, the element will leave the action and the surrounding elements will move to its position */
/* By that time all transitions have been completed. List-move has been removed, causing a lag */
.list-leave-active {
  position: absolute;
}
.list-enter..list-leave-to {
  opacity: 0;
  transform: translateY(30px);
}
Copy the code

This gives it a silky feel, and the CSS above can be further simplified:

/* Add transition directly to the element */
/* It applies to all elements that change, including v-move */
.list-item {
  display: inline-block;
  margin-right: 10px;
  transition: all 1s;
}
/* So v-move and V-active are not needed */
/* Just add an absolute positioning attribute when the element leaves */
.list-leave-active {
  position: absolute;
}
.list-enter..list-leave-to {
  opacity: 0;
  transform: translateY(30px);
}
Copy the code

Note: The internal implementation of V-Move, Vue, uses a simple animation queue called FLIP.

Elements that use FLIP transitions cannot be set todisplay: inline

So I can set it todisplay: inline-blockOr put it in Flex.