O Vue permite aplicar efeitos de transição durante a manipulação do DOM, como inserção, atualização ou remoção de elementos. Entre as opções disponíveis estão:
- Aplicação automática de classes para transições e enimações CSS.
- Integração com bibliotecas de animação CSS de terceiros, como Animate.css.
- Uso de funções de gancho JavaScript para manipulação direta do DOM.
- Suporte para bibliotecas de animação JavaScript, como Velocity.js.
O componente <transition> encapsula elementos ou componentes para adicionar transições de entrada/saída em cenários como renderização condicional (v-if), exibição condicional (v-show), componentes dinâmicos ou nós raiz. Ao inserir ou remover elementos dentro do <transition>, o Vue:
- Detecta automaticamente transições ou animações CSS e aplica classes nos momentos apropriados.
- Chama funções de gancho JavaScript fornecidas, se existirem.
- Executa as operações de DOM imediatamente no próximo quadro se nenhuma transição CSS ou gancho JavaScript for encontrado.
Transição de Elemento ou Componente Único
Exemplo básico de transição usando CSS para controlar a visibilidade de um elemento:
<script src="./lib/vue-2.4.0.js"></script>
<style>
.v-enter,
.v-leave-to {
opacity: 0;
transform: translateX(150px);
}
.v-enter-active,
.v-leave-active {
transition: all 0.8s ease;
}
</style>
<div id="aplicativo">
<input type="button" value="Alternar" @click="visivel = !visivel">
<transition>
<h3 v-if="visivel">Isso é um H3</h3>
</transition>
</div>
<script>
var vm = new Vue({
el: '#aplicativo',
data: {
visivel: false
}
});
</script>
Classes de Transição
Durante a entrada/saída, seis classes são alternadas com o prefixo padrão v-:
v-enter: estado inicial antes da inserção.v-enter-active: estado durante a transição de entrada.v-enter-to: estado final após a entrada (versão 2.1.8+).v-leave: estado inicial ao iniciar a saída.v-leave-active: estado durante a transição de saída.v-leave-to: estado final após a saída (versão 2.1.8+).
Para personalizar o prefixo, use o atributo name em <transition>. Por exemplo, <transition name="customizado"> substituirá v- por customizado-.
Transições CSS
Defina diferentes animações de entrada e saída usando classes CSS personalizadas:
<style>
.animacao-entrada,
.animacao-saida {
opacity: 0;
transform: translateY(70px);
}
.animacao-entrada-ativa,
.animacao-saida-ativa {
transition: all 0.8s ease;
}
</style>
<div id="app">
<transition name="animacao">
<div v-if="mostrar">Conteúdo animado</div>
</transition>
</div>
Animações CSS
Enimações CSS funcionam de forma semelhante, mas a classe v-enter não é removida até o evento animationend. Exemplo com um efeito de escala:
<div id="exemplo">
<button @click="ativo = !ativo">Alternar</button>
<transition name="escala">
<p v-if="ativo">Texto com animação de escala</p>
</transition>
</div>
<script>
new Vue({
el: '#exemplo',
data: { ativo: true }
});
</script>
<style>
.escala-enter-ativo {
animation: entrada-escala 0.5s;
}
.escala-leave-ativo {
animation: entrada-escala 0.5s reverse;
}
@keyframes entrada-escala {
0% { transform: scale(0); }
50% { transform: scale(1.5); }
100% { transform: scale(1); }
}
</style>
Uso com Bibliotecas de Terceiros
Atributos como enter-active-class e leave-active-class permitem integrar com bibliotecas como Animate.css. Use :duration para controlar a duração:
<link rel="stylesheet" href="./lib/animate.css">
<div id="app">
<transition
enter-active-class="bounceIn"
leave-active-class="bounceOut"
:duration="{ enter: 200, leave: 400 }">
<h3 v-if="visivel" class="animated">Elemento animado</h3>
</transition>
</div>
Ganchos JavaScript
Funções de gancho como before-enter e leave permitem controlar animações via JavaScript. Use v-bind:css="false para desativar a detecção CSS:
<transition
@before-enter="iniciaEntrada"
@enter="executaEntrada"
@after-enter="finalizaEntrada">
<div v-show="bolaVisivel" class="bola"></div>
</transition>
<script>
methods: {
iniciaEntrada(el) {
el.style.transform = "translate(0, 0)";
},
executaEntrada(el, done) {
el.offsetWidth; // Força a atualização
el.style.transform = "translate(150px, 450px)";
el.style.transition = 'all 1s ease';
done();
},
finalizaEntrada(el) {
this.bolaVisivel = !this.bolaVisivel;
}
}
</script>
Transição de Listas com transition-group
Para listas renderizadas com v-for, use <transition-group> e defina uma chave única para cada item. O atributo appear aplica a transição no carregamento inicial, e tag especifica o elemento raiz:
<transition-group appear tag="ul">
<li v-for="(item, idx) in itens" :key="item.id" @click="remover(idx)">
{{ item.id }} - {{ item.nome }}
</li>
</transition-group>
<style>
.v-enter, .v-leave-to { opacity: 0; transform: translateY(80px); }
.v-enter-active, .v-leave-active { transition: all 0.6s ease; }
.v-move { transition: all 0.6s ease; }
.v-leave-active { position: absolute; }
</style>
Transição de Múltiplos Componentes
Use componentes dinâmicos com :is e o atributo mode para controlar a sequência de transição:
<div id="app">
<a href="#" @click.prevent="componenteAtual = 'login'">Login</a>
<a href="#" @click.prevent="componenteAtual = 'registro'">Registro</a>
<transition mode="out-in">
<component :is="componenteAtual"></component>
</transition>
</div>
<script>
Vue.component('login', { template: '<h3>Componente de Login</h3>' });
Vue.component('registro', { template: '<h3>Componente de Registro</h3>' });
new Vue({
el: '#app',
data: { componenteAtual: 'login' }
});
</script>
Transição de Múltiplos Elementos
Ao alternar entre elementos com a mesma tag, use v-if/v-else e atributos key distintos para garantir a transição correta:
<transition>
<button v-if="editando" key="salvar">Salvar</button>
<button v-else key="editar">Editar</button>
</transition>
<transition>
<button :key="estado">
{{ mensagemBotao }}
</button>
</transition>
Propriedades computadas podem simplificar a lógica, como no exemplo acima, onde mensagemBotao varia com base no estado do documento.