https://cn.vuejs.org/v2/guide/transitions.html
vue的动画范围是:
- 进入离开动画:<transition name='xx'>: v-if / v-show、动态组件
- 列表动画:<transition-group>: li渲染
几个主要的类名:
- xx-enter: 进入之前的类名,从什么状态开始动画,
- xx-enter-active:动画的过程,一般用了设置transition
- xx-leave-to: 移除后的动画,被dom移除之前的状态;
- xx-leave-active:
<transition>的几个重要属性:
- appear:刚出现就用动画
- mode: 'in-out'或‘out-in’,表示v-if/v-show新旧两个元素的交替出现顺序。不写默认是同时动画。
注意:
1.如果两元素有间隔,可以用绝对定位
2.两个元素如果同名,两个元素需要加key以区分是不同的元素,否则diff算法会认为两个元素tagName一样,是同一个元素
<transition-group name='xx'>的重要属性:
- tag: <transition-group>被渲染成什么元素,默认span;
- xx-move: 类名,同leave-active和enter-active用于排序时候的过度,表示重新打乱顺序时候的动画效果
<template> <div class="transform-container"> <!-- 示例1 --> <!-- <button @click='show=!show'>show</button> <transition name='demo-one'> <div class="show" v-if="show">11</div> </transition> --> <!-- 示例二 :动态组件--> <!-- <button @click="titleLevel ++">level -</button> <button @click="titleLevel --">level +</button> <transition name='level' mode="in-out"> <component :is="'h'+titleLevel" :key='titleLevel'>aaaa</component> </transition> --> <!-- 示例三:轮播图效果 --> <!-- <p> <button @click="changeImg(index + 1, 'right')"><</button> <button @click="changeImg(index - 1, 'left')">></button> </p> <div class="wrapper"> <transition :name="`img-${direction}`"> <img v-if="arr" :src="arr[index]" alt="" :key="arr[index]" /> </transition> </div> --> <!-- 示例四:transition-group --> <input type="text" placeholder="输入任务" @keydown.enter="addTask" /> <p><button @click="resort">随机排序</button></p> <transition-group name="list" tag="ul"> <li v-for="(item, index) in taskList" v-bind:key="item" class="list-item"> {{ item }} <button @click="deleteItem(index)">完成</button> </li> </transition-group> </div> </template> <script> import Mock from 'mockjs'; const data = { code: 0, msg: '', // data:[] 'data|4': ['@image("100x100",@color)'], }; Mock.mock('/api/demo', 'get', data); export default { data() { return { arr: undefined, show: false, titleLevel: 3, index: 0, direction: 'left', taskList: [], }; }, methods: { deleteItem(i) { this.taskList.splice(i, 1); }, resort() { this.taskList.sort((a, b) => Math.random() - 0.5); }, addTask(e) { this.taskList.push(e.target.value); e.target.value = ''; }, changeImg(index, direction) { this.direction = direction; const len = this.arr.length; if (index >= len) { index = 0; } else if (index < 0) { index = len - 1; } this.index = index; }, }, async created() { const arr = await this.$http.get('/api/demo'); this.arr = arr; }, }; </script> <style scoped> .list-enter-active, .list-leave-active, .list-move { transition: 0.5s; } .list-enter { transform: translateX(-200px); opacity: 0; } .list-leave-to { transform: translateX(200px); opacity: 0; } button { margin-left: 50px; } .show { 100px; height: 100px; background: red; } .wrapper { 100px; height: 100px; position: relative; margin: 200px; /* overflow: hidden; */ } img { position: absolute; left: 0; border-radius: 50%; } .img-right-enter, .img-left-leave-to { transform: translateX(100px); opacity: 0; } .img-right-leave-to, .img-left-enter { transform: translateX(-100px); opacity: 0; } .img-left-enter-active, .img-right-leave-active, .img-right-enter-active, .img-left-leave-active { transition: 1s; } .demo-one-enter, .demo-one-leave-to, .level-enter, .level-leave-to { opacity: 0; } .demo-one-enter-active, .demo-one-leave-active, .level-enter-active, .level-leave-active { transition: 3s; } </style>