Transições de Visibilidade e Listas

Visão Geral

Vue disponibiliza uma variedade de maneiras para a aplicação de efeitos de transição quando itens são inseridos, atualizados, ou removidos do DOM. Isto inclue ferramentas para:

Nesta página, nós apenas falaremos sobre transições de entrada, saída, e de lista, mas você pode ver a próxima seção para transição de estados.

Transição Individual de Elementos

Vue disponibiliza um componente encapsulador (wrapper) chamado transition , permitindo que você adicione transição de entrada/saída para qualquer elemento ou componente dentro do seguinte contexto:

Aqui está um exemplo destes em ação:

<div id="demo">
<button v-on:click="show = !show">
Alternar
</button>
<transition name="fade">
<p v-if="show">olá</p>
</transition>
</div>
new Vue({
el: '#demo',
data: {
show: true
}
})
.fade-enter-active, .fade-leave-active {
transition: opacity .5s
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0
}

olá

Quando um elemento dentro de um componente transition é inserido ou removido, eis o que acontece:

  1. Vue irá automaticamente procurar se o elemento alvo tem transições CSS ou animações aplicadas. Caso positivo, as classes de transições CSS serão adicionadas/removidas nos momentos apropriados.

  2. Se o componente de transição fornece Gatilhos por JavaScript, estes gatilhos serão invocados nos momentos apropriados.

  3. Se nenhuma transição/animação CSS é detectada e nenhum JavaScript hook é fornecido, as operações de inserção e/ou remoção no DOM serão executadas imediatamente no próximo frame (Nota: isto é uma animação de frame do browser, diferente do conceito de nextTick do Vue).

Classes de Transição

Existem seis classes aplicadas para transição de entrada/saída.

  1. v-enter: Inicia o estado de entrada. Aplicado antes do elemento ser inserido, removido depois de um frame.

  2. v-enter-active: Ativa e termina o estado de entrada. Aplicado antes do elemento ser inserido, removido quando a transição/animação termina.

  3. v-enter-to: Disponível apenas nas versões 2.1.8+. Estado final de entrada. Adicionado um frame após o elemento ser inserido (ao mesmo tempo que v-enter é removido), removido quando a transição/animação termina.

  4. v-leave: Ativa o estado de saída. Aplicado quando a transição de saída é acionada, removido depois de um frame.

  5. v-leave-active: Estado ativo de saída. Aplicado duranto toda a fase de saída. Adicionado imediatamente quando a transição de saída é disparada, removido quando a transição/animação termina. Esta clase pode ser usada para definir a duração, atraso e a curva da transição de saída.

  6. v-leave-to: Disponível apenas nas versões 2.1.8+. Estado final da saída. Adicionado um frame após a transição de saída ser disparada (ao mesmo tempo que v-leave é removido), removida quando a transição/animação termina.

Diagrama de Transição

Cada uma destas classes serão prefixadas com o nome da transição. Aqui, o prefixo v- é padrão quando você utiliza o elemento <transition> sem nome. Se você, por exemplo, utilizar <transition name="my-transition"> a classe v-enter seria, no entanto, my-transition-enter.

v-enter-active e v-leave-active permitem especificar diferentes progressões de curvas para transição de entrada/saída, a qual você verá um exemplo na seção seguinte.

Transição CSS

Um dos tipos mais comuns de transição se utiliza de transições CSS. Segue um exemplo:

<div id="exemplo-1">
<button @click="show = !show">
Alterna renderização
</button>
<transition name="slide-fade">
<p v-if="show">olá</p>
</transition>
</div>
new Vue({
el: '#exemplo-1',
data: {
show: true
}
})
/* Animações de entrada e saída podem utilizar diferentes  */
/* funções de duração e de tempo. */
.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
/* .slide-fade-leave-active below version 2.1.8 */ {
transform: translateX(10px);
opacity: 0;
}

olá

Animações CSS

Animações CSS são aplicadas da mesma forma que as transições CSS, sendo que a diferença é que v-enter não é removido imediatamente após o elemento ser inserido, mas sim no evento animationend.

Aqui segue um exemplo, omitindo as regras de prefixo CSS, por uma questão de brevidade:

<div id="exemplo-2">
<button @click="show = !show">Alternar visualização</button>
<transition name="bounce">
<p v-if="show">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris facilisis enim libero, at lacinia diam fermentum id. Pellentesque habitant morbi tristique senectus et netus.</p>
</transition>
</div>
new Vue({
el: '#exemplo-2',
data: {
show: true
}
})
.bounce-enter-active {
animation: bounce-in .5s;
}
.bounce-leave-active {
animation: bounce-in .5s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris facilisis enim libero, at lacinia diam fermentum id. Pellentesque habitant morbi tristique senectus et netus.

Classes de Transição Personalizadas

Você também pode especificar uma classe de transição personalizada fornecendo os seguintes atributos:

Estes irão sobrescrever os nomes convencionais das classes. Isso é especialmente útil quando você quer combinar o sistema de transição do Vue com outra biblioteca CSS de animação já existente. como Animate.css.

Aqui segue um exemplo:

<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">

<div id="example-3">
<button @click="show = !show">
Alterna renderização
</button>
<transition
name="custom-classes-transition"
enter-active-class="animated tada"
leave-active-class="animated bounceOutRight"
>
<p v-if="show">olá</p>
</transition>
</div>
new Vue({
el: '#exemplo-3',
data: {
show: true
}
})

olá

Usando Transição e Animação juntos

Vue necessida escutar eventos para que consiga saber quando uma transição acabou. Os eventos podem ser transitionend ou animationend, dependendo do tipo de regra CSS aplicada. Se você utilizar apenas uma ou outra, Vue detectará automaticamente o tipo correto.

No entanto, em alguns casos, você poderá usar os dois tipos em um só elemento, como por exemplo, ter uma animação CSS que será acionada pelo Vue, juntamente com um efeito de transição CSS acionado pelo hover. Nestes casos, você terá que declarar explicitamente o tipo de evento que você gostaria que o Vue utilizasse em um atributo type, com o valor animation ou transition.

Duração Explícita de Transição

Novo em 2.2.0+

Na maioria dos casos, Vue consegue automaticamente detectar quando a animação terminou. Por padrão, Vue aguarda pelo primeiro evento transitionend ou animationend no elemento raiz da transição. Porém, nem sempre isso é o desejado - por exemplo, nós podemos ter uma transição coreografada onde alguns dos elementos filhos tem tempos diferentes em relação ao elemento raiz.

Nestes casos você pode especificar uma duração (em milisegundos) usando a propriedade duration no component <transition>:

<transition :duration="1000">...</transition>

Você também pode especificar valores separados para a duração de entrada e saída:

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

Gatilhos por JavaScript

Você também pode definir os gatilhos (em inglês, JavaScript hooks) nos atributos:

<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>
// ...
methods: {
// --------
// ENTRANDO
// --------

beforeEnter: function (el) {
// ...
},
// o callback de finalização é opcional quando
// utilizado em combinação com CSS
enter: function (el, done) {
// ...
done()
},
afterEnter: function (el) {
// ...
},
enterCancelled: function (el) {
// ...
},

// --------
// SAINDO
// --------

beforeLeave: function (el) {
// ...
},
// o callback de finalização é opcional quando
// utilizado em combinação com CSS
leave: function (el, done) {
// ...
done()
},
afterLeave: function (el) {
// ...
},
// leaveCancelled apenas disponível com v-show
leaveCancelled: function (el) {
// ...
}
}

Estes gatilhos podem ser utilizados em combinação com transição/animação CSS ou sozinhos.

Ao utilizar transições puramente JavaScript, os callbacks done para os gatilhos enter e o leave são obrigatórios. Caso contrário, serão invocados de forma síncrona e a transição terá um fim imediato.

Ao utilizar transições puramente JavaScript, é uma boa ideia adicionar explicitamente v-bind:css="false" para que o Vue possa pular a detecção de CSS. Isso também previne que regras CSS interfiram acidentalmente na transição.

Agora vamos mergulhar em um exemplo. Segue uma transição JavaScript com Velocity.js:

<!--
Velocity funciona muito parecido com o jQuery.animate e é uma excelente opção para animações JavaScript
-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>

<div id="exemplo-4">
<button @click="show = !show">
Alternar
</button>
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:leave="leave"
v-bind:css="false"
>
<p v-if="show">
Demo
</p>
</transition>
</div>
new Vue({
el: '#exemplo-4',
data: {
show: false
},
methods: {
beforeEnter: function (el) {
el.style.opacity = 0
},
enter: function (el, done) {
Velocity(el, { opacity: 1, fontSize: '1.4em' }, { 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 })
}
}
})

Demo

Transição na Renderização Inicial

Se você quiser aplicar a transição na renderização inicial de um nó, basta adicionar o atributo appear:

<transition appear>
<!-- ... -->
</transition>

Por padrão, isso utilizará a transição especificada para entrada e saída. Se você desejar, poderá ainda especificar classes CSS específicas:

<transition
appear
appear-class="custom-appear-class"
appear-to-class="custom-appear-to-class" (2.1.8+)
appear-active-class="custom-appear-active-class"
>
<!-- ... -->
</transition>

e ganchos JavaScript personalizados

<transition
appear
v-on:before-appear="customBeforeAppearHook"
v-on:appear="customAppearHook"
v-on:after-appear="customAfterAppearHook"
v-on:appear-cancelled="customAppearCancelledHook"
>
<!-- ... -->
</transition>

Transição entre Elementos

Nós discutiremos sobre transição entre Componentes em breve, mas você pode realizar transição entre elementos puros utilizando v-if/v-else. Uma das transições de dois elementos mais comum é entre um recipiente de lista e uma mensagem descrevendo uma lista vazia:

<transition>
<table v-if="items.length > 0">
<!-- ... -->
</table>
<p v-else>Desculpe, nenhum item encontrado.</p>
</transition>

Isso funciona bem, mas existe uma ressalva a qual precisamos estar atentos:

Quando alternamos entre elementos com a mesma tag, você precisa informar o Vue que eles são elementos distintos por meio do atributo único key. Caso contrário, o compilador do Vue irá substituir apenas o conteúdo do elemento por questões de eficiência. Mesmo quando tecnicamente não necessário, é considerado uma boa prática sempre utilizar o atributo key nos múltiplos itens dentro de um componente <transition>

Por exemplo:

<transition>
<button v-if="isEditing" key="save">
Salvar
</button>
<button v-else key="edit">
Editar
</button>
</transition>

Nestes casos você também poderá usar o atributo key para realizar transições entre diferentes estados de um mesmo elemento. Ao invés de utilizar v-if e v-else, o exemplo a seguir pode ser reescrito da seguinte forma:

<transition>
<button v-bind:key="isEditing">
{{ isEditing ? 'Salvar' : 'Editar' }}
</button>
</transition>

Também é possível realizar transições entre qualquer número de elementos, utilizando múltiplos v-if ou vinculando um elemento único à uma propriedade dinâmica. Por exemplo:

<transition>
<button v-if="docState === 'saved'" key="saved">
Editar
</button>
<button v-if="docState === 'edited'" key="edited">
Salvar
</button>
<button v-if="docState === 'editing'" key="editing">
Cancelar
</button>
</transition>

Which could also be written as:

<transition>
<button v-bind:key="docState">
{{ buttonMessage }}
</button>
</transition>
// ...
computed: {
buttonMessage: function () {
switch (this.docState) {
case 'saved': return 'Editar'
case 'edited': return 'Salvar'
case 'editing': return 'Cancelar'
}
}
}

Modos de Transição

Ainda temos um problema no entanto. Tente clicar no botão abaixo:

Por estarem transicionando entre o botão “ligar” e o botão “desligar”, ambos os botões são renderizados - uma transição sai enquanto a outra transição entra. Este é o comportamento padrão do <transition> - entrada e saída acontecem simultaneamente.

Às vezes isso funciona perfeitamente, como quando realizamos transições de itens que são absolutamente posicionados no topo uns dos outros:

E também utilizar translate para que se pareça com uma transição slide:

No entanto, transição de entrada e saída simultânea nem sempre são desejadas, neste caso, o Vue oferece uma alternativa modos de transição:

Agora vamos atualizar a transição para os nossos botões ligar/desligar com out-in:

<transition name="fade" mode="out-in">
<!-- ... the buttons ... -->
</transition>

Com a adição de um atributo, corrigimos nossa transição original sem ter de adicionar qualquer estilo especial.

O modo in-out não é utilizado com frequência, mas às vezes pode ser útil para um efeito de transição ligeiramente diferente. Vamos tentar combiná-lo com a transição slide-fade que trabalhamos anteriormente:

Bem legal, certo?

Transições entre Componentes

Transições entre componentes são ainda mais simples - nem precisamos do atributo key. Ao invés disso, encapsulamos em um componente dinâmico:

<transition name="component-fade" mode="out-in">
<component v-bind:is="view"></component>
</transition>
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>'
}
}
})
.component-fade-enter-active, .component-fade-leave-active {
transition: opacity .3s ease;
}
.component-fade-enter, .component-fade-leave-to
/* .component-fade-leave-active below version 2.1.8 */ {
opacity: 0;
}

Transições em Listas

Até agora, nós temos transições para:

Então que tal ter uma lista de itens e renderizá-los simultaneamente com o v-for, por exemplo? Neste caso, utilizaremos o componente <transition-group>. Antes de entrarmos em um exemplo, existem algumas coisas que são importantes saber sobre este componente:

Transição de Entrada/Saída de Lista

Agora vamos analisar um exemplo, transicionando entrada e saída com as mesmas classes CSS que usamos anteriormente:

<div id="list-demo" class="demo">
<button v-on:click="add">Adicionar</button>
<button v-on:click="remove">Remover</button>
<transition-group name="list" tag="p">
<span v-for="item in items" v-bind:key="item" class="list-item">
{{ item }}
</span>
</transition-group>
</div>
new Vue({
el: '#list-demo',
data: {
items: [1,2,3,4,5,6,7,8,9],
nextNum: 10
},
methods: {
randomIndex: function () {
return Math.floor(Math.random() * this.items.length)
},
add: function () {
this.items.splice(this.randomIndex(), 0, this.nextNum++)
},
remove: function () {
this.items.splice(this.randomIndex(), 1)
},
}
})
.list-item {
display: inline-block;
margin-right: 10px;
}
.list-enter-active, .list-leave-active {
transition: all 1s;
}
.list-enter, .list-leave-to /* .list-leave-active below version 2.1.8 */ {
opacity: 0;
transform: translateY(30px);
}
{{ item }}

Existe um problema com este exemplo. Quando você adiciona ou remove um item, aqueles em torno dele se encaixam instantaneamente ao invés de fazer a transição suavemente. Nós iremos corrigir isto mais tarde.

Transições de Movimento de Lista

O componente <transition-group> tem outro truque na manga. Ele não só tem animação de entrada e saída, como também na mudança de posição. O único conceito novo que você precisa saber para usar esta feature é a adição de da classe v-move, a qual é inserida quando os itens estão mudando suas posições. Assim como outras classes, elas serão prefixadas com o valor fornecido pelo atributo name e você poderá especificar manualmente uma classe com o atributo move-class.

Esta classe é útil para especificar o tempo de transição ou a suavidade da curva, como você pode ver adiante:

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

<div id="flip-list-demo" class="demo">
<button v-on:click="shuffle">Misturar</button>
<transition-group name="flip-list" tag="ul">
<li v-for="item in items" v-bind:key="item">
{{ item }}
</li>
</transition-group>
</div>
new Vue({
el: '#flip-list-demo',
data: {
items: [1,2,3,4,5,6,7,8,9]
},
methods: {
shuffle: function () {
this.items = _.shuffle(this.items)
}
}
})
.flip-list-move {
transition: transform 1s;
}
  • {{ item }}
  • Isto pode parecer mágica, mas internamente Vue está aplicando uma técnica de animação chamada FLIP para suavemente transitar elementos da posição antiga para a posição nova utilizando transformações CSS.

    Nós podemos combinar esta técnica com a nossa implementação anterior para animar qualquer mudança na nossa lista!

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

    <div id="list-complete-demo" class="demo">
    <button v-on:click="shuffle">Misturar</button>
    <button v-on:click="add">Adicionar</button>
    <button v-on:click="remove">Remover</button>
    <transition-group name="list-complete" tag="p">
    <span
    v-for="item in items"
    v-bind:key="item"
    class="list-complete-item"
    >
    {{ item }}
    </span>
    </transition-group>
    </div>
    new Vue({
    el: '#list-complete-demo',
    data: {
    items: [1,2,3,4,5,6,7,8,9],
    nextNum: 10
    },
    methods: {
    randomIndex: function () {
    return Math.floor(Math.random() * this.items.length)
    },
    add: function () {
    this.items.splice(this.randomIndex(), 0, this.nextNum++)
    },
    remove: function () {
    this.items.splice(this.randomIndex(), 1)
    },
    shuffle: function () {
    this.items = _.shuffle(this.items)
    }
    }
    })
    .list-complete-item {
    transition: all 1s;
    display: inline-block;
    margin-right: 10px;
    }
    .list-complete-enter, .list-complete-leave-to
    /* .list-complete-leave-active below version 2.1.8 */ {
    opacity: 0;
    transform: translateY(30px);
    }
    .list-complete-leave-active {
    position: absolute;
    }
    {{ item }}

    É importante notar que as transições FLIP não funcionam com elementos display: inline. Como alternativa, você pode usar display: inline-block ou colocar os elementos dentro de um contexto flex.

    Estas animações FLIP também não são limitadas a um único eixo. Itens em uma grade multidimensional também podem ser transicionados:

    Sudoku para preguiçosos

    Clique no botão misturar até ganhar.

    {{ cell.number }}

    Escalonamento de Transições de Lista

    Ao comunicar com transições JavaScript por meio de atributos de dados, também é possível escalonar as transições em uma lista:

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

    <div id="staggered-list-demo">
    <input v-model="query">
    <transition-group
    name="staggered-fade"
    tag="ul"
    v-bind:css="false"
    v-on:before-enter="beforeEnter"
    v-on:enter="enter"
    v-on:leave="leave"
    >
    <li
    v-for="(item, index) in computedList"
    v-bind:key="item.msg"
    v-bind:data-index="index"
    >{{ item.msg }}</li>
    </transition-group>
    </div>
    new Vue({
    el: '#staggered-list-demo',
    data: {
    query: '',
    list: [
    { msg: 'Bruce Lee' },
    { msg: 'Jackie Chan' },
    { msg: 'Chuck Norris' },
    { msg: 'Jet Li' },
    { msg: 'Kung Fury' }
    ]
    },
    computed: {
    computedList: function () {
    var vm = this
    return this.list.filter(function (item) {
    return item.msg.toLowerCase().indexOf(vm.query.toLowerCase()) !== -1
    })
    }
    },
    methods: {
    beforeEnter: function (el) {
    el.style.opacity = 0
    el.style.height = 0
    },
    enter: function (el, done) {
    var delay = el.dataset.index * 150
    setTimeout(function () {
    Velocity(
    el,
    { opacity: 1, height: '1.6em' },
    { complete: done }
    )
    }, delay)
    },
    leave: function (el, done) {
    var delay = el.dataset.index * 150
    setTimeout(function () {
    Velocity(
    el,
    { opacity: 0, height: 0 },
    { complete: done }
    )
    }, delay)
    }
    }
    })
  • {{ item.msg }}
  • Transições Reutilizáveis

    Transições podem ser reutilizadas por meio do sistema de componentes do Vue. Para criar uma transição reutilizável, tudo o que você precisa fazer é inserir um componente <transition> ou <transition-group> em sua raíz, e então adicionar qualquer child dentro do componente de transição.

    Aqui segue um exemplo utilizando um modelo de componente:

    Vue.component('my-special-transition', {
    template: '\
    <transition\
    name="very-special-transition"\
    mode="out-in"\
    v-on:before-enter="beforeEnter"\
    v-on:after-enter="afterEnter"\
    >\
    <slot></slot>\
    </transition>\
    ',
    methods: {
    beforeEnter: function (el) {
    // ...
    },
    afterEnter: function (el) {
    // ...
    }
    }
    })

    E componentes funcionais são especialmente bem adequado para esta tarefa:

    Vue.component('my-special-transition', {
    functional: true,
    render: function (createElement, context) {
    var data = {
    props: {
    name: 'very-special-transition',
    mode: 'out-in'
    },
    on: {
    beforeEnter: function (el) {
    // ...
    },
    afterEnter: function (el) {
    // ...
    }
    }
    }
    return createElement('transition', data, context.children)
    }
    })

    Transições Dinâmicas

    Sim, até as transições no Vue são orientadas a dados (data-driven)! O exemplo mais básico de uma transição dinâmica vincula o atributo name à uma propriedade dinâmica.

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

    Isto pode ser útil quando você tiver definido transições/animações CSS usando as convenções de classes de transição do Vue e quer alternar entre elas.

    No entanto, qualquer atributo de transição pode ser vinculado dinamicamente. E não apenas atributos. Já que gatilhos de eventos são métodos, possuem acesso a qualquer dado no contexto. Isto significa que suas transições JavaScript podem se comportar de forma diferente dependendo do estado de seu componente.

    <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">olá</p>
    </transition>
    <button
    v-if="stop"
    v-on:click="stop = false; show = false"
    >Começar a animar</button>
    <button
    v-else
    v-on:click="stop = true"
    >Pare!</button>
    </div>
    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
    }
    }
    )
    }
    }
    })
    Fade In: Fade Out:

    olá

    Finalmente, a última forma para a criação de transições dinâmicas é por meio de componentes que aceitam que suas props possam mudar a natureza da transição a ser utilizada. Pode parecer clichê, mas o único limite é sua imaginação.