首页 > 编程笔记 > JavaScript笔记
Vue transition-group列表过渡详解
在 Vue 中,可以使用 transition 组件实现过渡和动画效果,而渲染整个列表则使用 <transition-group> 组件。
<transition-group> 组件有以下几个特点:
【实例】列表的进入/离开过渡。
图 1 添加效果
单击“移除”按钮删除一个数,触发离开效果,效果如下图所示:
图 2 删除效果
这个例子有一个问题,当添加和移除元素的时候,周围的元素会瞬间移动到它们新布局的位置,而不是平滑地过渡,接下来我们会解决这个问题。
要使用这个新功能,只需了解新增的 v-move class,它会在元素改变定位的过程中应用。与之前的类名一样,可以通过 name 属性来自定义前缀,也可以通过 move-class 属性手动设置。
v-move 对于设置过渡的切换时机和过渡曲线非常有用。
【实例】列表的排序过渡。
图 3 页面加载效果
单击“排序过渡”按钮,将会重新排列数字顺序,效果如下图所示:
图 4 重新排列效果
在上面的示例中,Vue 使用了一个叫 FLIP 的简单动画队列,使用其中的 transforms 将元素从之前的位置平滑过渡到新的位置。
【实例】列表的交错过渡。
图 5 页面加载效果
在输入框中输入“a”,可以发现过滤掉了不带 a 的选项,如下图所示:
图 6 过滤掉一些数据
<transition-group> 组件有以下几个特点:
- 不同于 <transition>,它会以一个真实元素呈现:默认为一个 <span>,也可以通过 tag 属性更换为其他元素。
- 过渡模式不可用,因为我们不再相互切换特有的元素。
- 内部元素总是需要提供唯一的 key 属性值。
- CSS 过渡的类将会应用在内部的元素中,而不是这个组/容器本身。
列表的进入/离开过渡
下面通过一个例子来学习如何设计列表的进入/离开过渡效果。【实例】列表的进入/离开过渡。
<style> .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); } </style> <div id="app" class="demo"> <button v-on:click="add">添加</button> <button v-on:click="remove">移除</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> <!--引入Vue文件--> <script src="https://unpkg.com/vue@next"></script> <script> //创建一个应用程序实例 const vm= Vue.createApp({ //该函数返回数据对象 data(){ return{ items: [10,20,30,40,50,60,70,80,90], 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) } } //在指定的DOM元素上装载应用程序实例的根组件 }).mount('#app'); </script>在 Chrome 浏览器中运行程序,单击“添加”按钮,向数组中添加内容,触发进入效果,效果如下图所示:
图 1 添加效果
单击“移除”按钮删除一个数,触发离开效果,效果如下图所示:
图 2 删除效果
这个例子有一个问题,当添加和移除元素的时候,周围的元素会瞬间移动到它们新布局的位置,而不是平滑地过渡,接下来我们会解决这个问题。
列表的排序过渡
<transition-group> 组件还有一个特殊之处,不仅可以进入和离开动画,还可以改变定位。要使用这个新功能,只需了解新增的 v-move class,它会在元素改变定位的过程中应用。与之前的类名一样,可以通过 name 属性来自定义前缀,也可以通过 move-class 属性手动设置。
v-move 对于设置过渡的切换时机和过渡曲线非常有用。
【实例】列表的排序过渡。
<script src="lodash.js"></script> <style> .flip-list-move { transition: transform 1s; } </style> <div id="app" class="demo"> <button v-on:click="shuffle">排序过渡</button> <transition-group name="flip-list" tag="ul"> <li v-for="item in items" v-bind:key="item"> {{ item }} </li> </transition-group> </div> <!--引入Vue文件--> <script src="https://unpkg.com/vue@next"></script> <script> //创建一个应用程序实例 const vm= Vue.createApp({ //该函数返回数据对象 data(){ return{ items: [10,20,30,40,50,60,70,80,90], nextNum: 10 } }, methods: { shuffle: function () { this.items = _.shuffle(this.items) } } //在指定的DOM元素上装载应用程序实例的根组件 }).mount('#app'); </script>在 Chrome 浏览器中运行程序,效果如下图所示:
图 3 页面加载效果
单击“排序过渡”按钮,将会重新排列数字顺序,效果如下图所示:
图 4 重新排列效果
在上面的示例中,Vue 使用了一个叫 FLIP 的简单动画队列,使用其中的 transforms 将元素从之前的位置平滑过渡到新的位置。
列表的交错过渡
通过 data 选项与 JavaScript 通信,就可以实现列表的交错过渡。下面通过一个过滤器的示例看一下效果。【实例】列表的交错过渡。
<script src="velocity.js"></script> <div id="app" class="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> <!--引入Vue文件--> <script src="https://unpkg.com/vue@next"></script> <script> //创建一个应用程序实例 const vm= Vue.createApp({ //该函数返回数据对象 data(){ return{ query: '', list: [ { msg: 'apple' }, { msg: 'almond'}, { msg: 'banana' }, { msg: 'coconut' }, { msg: 'date' }, { msg: 'mango' }, { msg: 'apricot'}, { msg: 'banana' }, { msg: 'bitter'} ] } }, 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) } } //在指定的DOM元素上装载应用程序实例的根组件 }).mount('#app'); </script>在 Chrome 浏览器中运行程序,效果如下图所示:
图 5 页面加载效果
在输入框中输入“a”,可以发现过滤掉了不带 a 的选项,如下图所示:
图 6 过滤掉一些数据