这里是官方文档:http://cn.vuejs.org/v2/guide/transitions.html
一、开始
我们可以随便在一个 vue 文件下写上(一个模板文件下):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| <template> <div id="movie"> <button @click="showMenu" class="btn">{{text}}</button> <!--动画部分--> <transition name="move"> <div class="menu" v-show="show"> <div class="inner inner-1">1</div> </div> </transition> </div> </template> <script> export default { data() { return { show: false }; }, methods: { showMenu() { this.show = !this.show; } }, computed: { text() { return this.show ? '收' : '开'; } } }; </script> <style> #movie{ margin-top:10px; } .btn{ position: fixed; top:60px; left:50%; z-index:10; width:50px; height:50px; line-height:50px; border-radius: 50%; border:none; outline:none; color:#fff; font-size:18px; background:orange; } .inner-1{ display: inline-block; position:absolute; width:30px; height:30px; line-height:30px; border-radius:50%; background: red; text-align:center; color:#fff; transition:all 0.4s; left:-50px; top:20px; } .menu{ position:fixed; top:60px; left:50%; width:50px; height:50px; border-radius:50%; transition:all 0.7s linear; } /*上面主要都是样式代码*/ .move-enter-active > .inner-1{ transform: translate3d(0,0,0); } .move-enter > .inner-1, .move-leave-active >.inner-1{ transition-timing-function: ease-in-out ; transform:translate3d(60px,0,0) ; } </style>
|
再点开这个页面,可以看到一个最简单的过渡效果:
这里,我把enter理解为动画的起始状态,leave-active理解为返回最终状态(这个过渡效果类似 CSS3 的 animation)
其实也可以直接用 CSS3 的 animation,只需要做如下修改:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| <template> <div id="movie"> <div id="example-2"> <button @click="showMenu" class="btn">{{text}}</button> <transition name="bounce"> <p style="padding-left:50px" v-if="show">Look at me!</p> </transition> </div> </div> </template> <script> export default { data() { return { show: false }; }, methods: { showMenu() { this.show = !this.show; } }, computed: { text() { return this.show ? '逝' : '现'; } } }; </script> <style> #movie{ margin-top:10px; } .btn{ position: fixed; top:60px; left:50%; z-index:10; width:50px; height:50px; line-height:50px; border-radius: 50%; border:none; outline:none; color:#fff; font-size:18px; background:orange; } .bounce-enter-active { animation: bounce-in 2s; } .bounce-leave-active { animation: bounce-out 2s; } @keyframes bounce-in { 0% { transform: scale(0); } 50% { transform: scale(1.5); } 100% { transform: scale(1); } } @keyframes bounce-out { 0% { transform: scale(1); } 50% { transform: scale(1.5); } 100% { transform: scale(0); } }
</style>
|
运行看下效果:
其实就 vue 帮你加了个 class 又自动帮你移除了
二、多个组件过渡
组件的过渡可以痛通过绑定选中值实现
这里我们再修改下 Vue 文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| <template> <div id="movie"> <div class="radio"> <input type="radio" id="one" value="v-a" v-model="view"> <label for="one">A</label> <input type="radio" id="two" value="v-b" v-model="view"> <label for="two">B</label> </div> <div class="show"> <transition name="component-fade" mode="out-in"> <component :is="view"></component> </transition> </div> </div> </template> <script> export default { data() { return { view: 'v-a', picked: 'one' }; }, components: { 'v-a': { template: '<div>Component A</div>' }, 'v-b': { template: '<div>Component B</div>' } } }; </script> <style> #movie{ margin-top:25px; width:100%; height:200px; display:flex; flex-direction: column; align-items: center; } .component-fade-enter-active .conpoment-fade-leave-active{ opacity: 1; transition: all 0.5s ease; } .component-fade-enter, .component-fade-leave-active { opacity: 0; } </style>
|
这样我们就可以在选择的数据变化时实现简单的过渡:
三、JavaScript 钩子
script 钩子其实就是一一设定绑定状态的变化,设置相对应的过渡效果,看下例子:
html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
| <div id="movie"> <img class="target" src="./basket.png"></img> <transition v-for="ball in balls" name="shooting" @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter"> <!--外层做纵向动画--> <div class="ball" v-show="ball.show"> <!--内层做横向动画--> <div class="inner"></div> </div> </transition> <img class="shoot" @click="shoot($event)" src="./player.png"></img> </div> ******script***** data() { return { balls: [ { show: false }, { show: false }, { show: false }, { show: false }, { show: false } ], dropBalls: [] }; }, methods: { shoot(el) { var balls = this.balls; for (let i in balls) { let ball = balls[i]; if (!ball.show) { ball.show = true; ball.el = el.target; this.dropBalls.push(ball); return; } } }, beforeEnter:function(el) { let count = this.balls.length; while (count--) { let ball = this.balls[count]; if (ball.show) { let rect = ball.el.getBoundingClientRect(); let left = rect.left ; console.log(el); let top = -(window.innerHeight - rect.top - 520); el.style.display = ''; el.style.webkitTransform = `translate3d(0,${top}px,0)`; el.style.transform = `translate3d(0,${top}px,0)`; let inner = el.getElementsByClassName('inner')[0]; inner.style.webkitTransform = `translate3d(${left}px,0,0)`; inner.style.transform = `translate3d(${left}px,0,0)`; } } }, enter:function(el) { /* eslint-disable no-unused-vars */ let refresh = el.offsetHeight; this.$nextTick(() => { el.style.webkitTransform = 'translate3d(0,0,0)'; el.style.transform = 'translate3d(0,0,0)'; let inner = el.getElementsByClassName('inner')[0]; inner.style.webkitTransform = 'translate3d(0,0,0)'; inner.style.transform = 'translate3d(0,0,0)'; }); }, afterEnter:function(el) { let ball = this.dropBalls.shift(); if (ball) { ball.show = false; el.style.display = 'none'; } } }
|
其实就是设置相应的变化位置,完成变化,最后看下效果:
四、表单过渡(transition-group)
其实这个 transition-group 相当于给每一个元素添加一个 transition,但需要指定唯一的标识 key,看下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <template> <div id="movie"> <div id="list-demo" class="demo"> <button v-on:click="add">Add</button> <transition-group name="list" tag="ul"> // key值为item <li v-for="(item,index) in items" :key="item" class="list-item" @click="deleteShow(index)">{{ item.text }} // 给删除按钮再加个动画 <transition name="move"> <button class="deleteButton" v-show="item.show" @click="deleteItem(index)">删除</button> </transition> </li> </transition-group> </div> </div> </template>
|
看上面的代码,其实就是和普通的 transition 是差不多的,只需理解为给每一个元素添加一个 transition 就行了,再看看样式代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| #movie{ margin-top:25px; width:100%; height:200px; display:flex; flex-direction: column; justify-content: flex-start; align-items: center; position:relative; } button{ left:50%; margin-left:-50px; position:relative; } .deleteButton { position:absolute; width:50px; height:30px; bottom:0; left:300px; } .list-item { position:relative; display: inline-block; width:300px; height:30px; margin:5px 40px; background:lightgrey; transition: all 0.5s linear; } /*进入的初始状态*/ .list-enter, .list-leave-active { opacity:0; transform: translateX(-300px); } /*列表平滑过渡*/ /*离开的状态*/
.list-leave-active { transform: translateX(-300px); position:absolute } .move-enter,.move-leave-active{ transform: translate3d(50px,0,0); opacity: 0; } .move-enter-active,.move-leave-active{ opacity: 1; transition: all 0.2s linear; } </style>
|
看下结果,实现了一个最简单transition-group:
最主要的是理解经历的状态以及状态的变化,添加相应的样式,就可以做出想要的效果了