详解Vue学习笔记进阶篇之列表过渡及其他


Posted in Javascript onJuly 17, 2017

本文将介绍Vue中的列表过渡,动态过渡, 以及可复用过渡是实现。

列表过渡

目前为止,关于过渡我们已经讲到:

  1. 单个节点
  2. 同一时间渲染多个节点中的一个

那么怎么同时渲染整个列表,比如使用 v-for ?在这种场景中,使用 <transition-group>组件。在我们深入例子之前,先了解关于这个组件的几个特点:

  1. 不同于 <transition>, 它会以一个真实元素呈现:默认为一个<span>。你也可以通过 tag 特性更换为其他元素。
  2. 内部元素 总是需要 提供唯一的 key属性值.列表的进入和离开过渡

现在让我们由一个简单的例子深入,进入和离开的过渡使用之前一样的 CSS 类名。

<div id="app1">
  <button @click="add">Add</button>
  <button @click="remove">Remove</button>
  <transition-group name="list" tag="p">
    <span v-for="item in items" :key="item" class="list-item">
      {{item}}
    </span>
  </transition-group>
</div>
.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);
    }
var app1 = new Vue({
  el:'#app1',
  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)
    }
  }
})

运行结果:

详解Vue学习笔记进阶篇之列表过渡及其他

这个例子有个问题,当添加和移除元素的时候,周围的元素会瞬间移动到他们的新布局的位置,而不是平滑的过渡,我们下面会解决这个问题。

列表的位移过渡

<transition-group> 组件还有一个特殊之处。不仅可以进入和离开动画,还可以改变定位。要使用这个新功能只需了解新增的v-move 特性,它会在元素的改变定位的过程中应用。像之前的类名一样,可以通过 name 属性来自定义前缀,也可以通过 move-class 属性手动设置。

v-move对于设置过渡的切换时机和过渡曲线非常有用,你会看到如下的例子:

<div id="app2">
  <button @click="shuffle">Shuffle</button>
  <transition-group name="flip-list" tag="ul">
    <li v-for="item in items" :key="item">
      {{item}}
    </li>
  </transition-group>
</div>
.flip-list-move {
   transition: transform 1s;
}
var app2 = new Vue({
  el:'#app2',
  data:{
    items:[1,2,3,4,5,6,7,8,9]
  },
  methods:{
    shuffle:function () {
      this.items = _.shuffle(this.items)
    }
  }
})

这个例子需要添加以下引用

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

运行结果:

详解Vue学习笔记进阶篇之列表过渡及其他

这个看起来很神奇,内部的实现,Vue 使用了一个叫 FLIP 简单的动画队列

使用 transforms 将元素从之前的位置平滑过渡新的位置。

我们将之前实现的例子和这个技术结合,使我们列表的一切变动都会有动画过渡。

<div id="app3" class="demo">
  <button @click="shuffle">Shuffle</button>
  <button @click="add">Add</button>
  <button @click="remove">Remove</button>
  <transition-group name="list-complete" tag="p">
    <span v-for="item in items" :key="item" class="list-complete-item">
      {{item}}
    </span>
  </transition-group>
</div>
.list-complete-item{
  transition: all 1s;
  display: inline-block;
  margin-right: 10px;
}
.list-complete-enter, .list-complete-leave-to{
  opacity: 0;
  transform: translateY(30px);
}
.list-complete-leave-active{
  position: absolute;
}
var app3 = new Vue({
  el:'#app3',
  data:{
    items:[1,2,3,4,5,6,7,8,9],
    nextNum:10
  },
  methods:{
    shuffle:function () {
      this.items = _.shuffle(this.items)
    },
    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)
    }
  }
})

运行结果:

详解Vue学习笔记进阶篇之列表过渡及其他

列表的渐进过渡

通过 data 属性与 JavaScript 通信 ,就可以实现列表的渐进过渡:

<div id="app4">
  <input v-model="query">
  <transition-group
    name="staggered-fade"
    tag="ul"
    :css="false"
    @before-enter="beforeEnter"
    @enter="enter"
    @leave="leave">
    <li v-for="(item, index) in computedList"
      :key="item.msg"
      :data-index="index">
      {{item.msg}}
    </li>
  </transition-group>
</div>
var app4 = new Vue({
  el:'#app4',
  data:{
    query:'',
    list:[
      {msg:'Bruce Lee'},
      {msg:'Jackie Chan'},
      {msg:'Chuck Norris'},
      {msg:'Jet Li'},
      {msg:'Kung Furry'},
      {msg:'Chain Zhang'},
      {msg:'Iris Zhao'},
    ]
  },
  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)
    }
  }
})

上述js代码需要添加对Velocity引用:

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

运行结果如下:

详解Vue学习笔记进阶篇之列表过渡及其他

可复用的过渡

过渡可以通过 Vue 的组件系统实现复用。要创建一个可复用过渡组件,你需要做的就是将<transition>或者 <transition-group>作为根组件,然后将任何子组件放置在其中就可以了。

下面的例子是将上一个列表渐进过渡的例子改为可复用的过渡的源码:

<div id="app5">
  <input v-model="query">
  <my-transition :query="query" :list="list">
    <li v-for="(item, index) in computedList"
      :key="item.msg"
      :data-index="index">
      {{item.msg}}
    </li>
  </my-transition>
</div>
Vue.component('my-transition', {
  template:`
  <transition-group
    name="staggered-fade"
    tag="ul"
    :css="false"
    @before-enter="beforeEnter"
    @enter="enter"
    @leave="leave">
    <slot></slot>
  </transition-group>`,
  props:['query', 'list'],
  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)
    }
  }
})

var app5 = new Vue({
  el:'#app5',
  data:{
    query:'',
    list:[
      {msg:'Bruce Lee'},
      {msg:'Jackie Chan'},
      {msg:'Chuck Norris'},
      {msg:'Jet Li'},
      {msg:'Kung Furry'},
      {msg:'Chain Zhang'},
      {msg:'Iris Zhao'},
    ]
  },
  computed:{
    computedList:function () {
      var vm = this
      return this.list.filter(function (item) {
        return item.msg.toLowerCase().indexOf(vm.query.toLowerCase()) !== -1
      })
    }
  },
})

效果与上一个例子一致:

详解Vue学习笔记进阶篇之列表过渡及其他

但是函数组件更适合完成这个任务。由于暂时还没有学到render函数,所以暂时先不实现render函数组件。后面学到的时候再做打算。

动态过渡

在 Vue 中即使是过渡也是数据驱动的!动态过渡最基本的例子是通过 name 特性来绑定动态值。

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

当你想用 Vue 的过渡系统来定义的 CSS 过渡/动画 在不同过渡间切换会非常有用。

所有的过渡特性都是动态绑定。它不仅是简单的特性,通过事件的钩子函数方法,可以在获取到相应上下文数据。这意味着,可以根据组件的状态通过 JavaScript 过渡设置不同的过渡效果。

<div id="app6">
  Fade In:
  <input type="range" v-model="fadeInDuration" min="0" :max="maxFadeDuration">
  Fade Out:
  <input type="range" v-model="fadeOutDuration" min="0" :max="maxFadeDuration">
  <transition
    v-bind:css="false"
    @before-enter="beforeEnter"
    @enter="enter"
    @leave="leave">
    <p v-if="show">hello chain</p>
  </transition>
  <button @click="stop = true">Stop it</button>
</div>
var app6 = new Vue({
  el: '#app6',
  data: {
    show: true,
    fadeInDuration: 1000,
    fadeOutDuration: 1000,
    maxFadeDuration: 1500,
    stop: false
  },
  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
          }
        }
      )
    }
  }
})

运行结果:

详解Vue学习笔记进阶篇之列表过渡及其他

其中例子里的mounted是在Vue挂载完成,也就是模板中的html渲染到html页面中时的一个钩子函数,只会执行一次。具体内容可以理解下Vue的生命周期,这里就不赘述了。

但是如果这里不使用mounted的话,也是可以用初始渲染来实现,只不过比较麻烦。实现的方法是:

在transition中加入appear钩子函数:@appear="appear",然后在vue实例的methods中添加appear方法:

appear: function (el, done) {
      var vm = this
      Velocity(el,
        { opacity: 1 },
        {
          duration: this.fadeInDuration,
          complete: function () {
            done()
            if (!vm.stop) vm.show = false
          }
        }
      )
    }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
fix-ie5.js扩展在IE5下不能使用的几个方法
Aug 20 Javascript
JQUERY CHECKBOX全选,取消全选,反选方法三
Aug 30 Javascript
js中更短的 Array 类型转换
Oct 30 Javascript
用Javascript评估用户输入密码的强度(Knockout版)
Nov 30 Javascript
原生JavaScript编写俄罗斯方块
Mar 30 Javascript
AngularJS向后端ASP.NET API控制器上传文件
Feb 03 Javascript
图文详解Heap Sort堆排序算法及JavaScript的代码实现
May 04 Javascript
JavaScript 函数的执行过程
May 09 Javascript
Vue组件实例间的直接访问实现代码
Aug 20 Javascript
jQuery实现购物车的总价计算和总价传值功能
Nov 28 jQuery
微信小程序开发问题之wx.previewImage
Dec 25 Javascript
在Vue环境下利用worker运行interval计时器的步骤
Aug 01 Javascript
js学使用setTimeout实现轮循动画
Jul 17 #Javascript
详解Vue2.x-directive的学习笔记
Jul 17 #Javascript
javascript  数组排序与对象排序的实例
Jul 17 #Javascript
jQuery常用选择器详解
Jul 17 #jQuery
js轮播图的插件化封装详解
Jul 17 #Javascript
Vue.js中extend选项和delimiters选项的比较
Jul 17 #Javascript
Vue.js中组件中的slot实例详解
Jul 17 #Javascript
You might like
使用PHP导出Word文档的原理和实例
2013/10/21 PHP
php根据分类合并数组的方法实例详解
2013/11/06 PHP
yii2的restful api路由实例详解
2019/05/14 PHP
jquery 全局AJAX事件使用代码
2010/11/05 Javascript
JavaScript 操作table,可以新增行和列并且隔一行换背景色代码分享
2013/07/05 Javascript
解析Jquery中如何把一段html代码动态写入到DIV中(实例说明)
2013/07/09 Javascript
JavaScript?Apple设备检测示例代码
2013/11/15 Javascript
AngularJS模仿Form表单提交的实现代码
2016/12/08 Javascript
JavaScript Uploadify文件上传实例
2017/02/28 Javascript
bootstrap3使用bootstrap datetimepicker日期插件
2017/05/24 Javascript
Angular 2父子组件数据传递之@Input和@Output详解(下)
2017/07/05 Javascript
vue+iview写个弹框的示例代码
2017/12/05 Javascript
详解Vue-cli webpack移动端自动化构建rem问题
2018/04/07 Javascript
JavaScript 2018 中即将迎来的新功能
2018/09/21 Javascript
JavaScript 中判断变量是否为数字的示例代码
2020/10/22 Javascript
[02:44]DOTA2英雄基础教程 钢背兽
2013/12/19 DOTA
[04:52]DOTA2亚洲邀请赛附加赛 TOP10精彩集锦
2015/01/29 DOTA
Python中encode()方法的使用简介
2015/05/18 Python
Python编程中time模块的一些关键用法解析
2016/01/19 Python
Python3中使用urllib的方法详解(header,代理,超时,认证,异常处理)
2016/09/21 Python
python实现简易通讯录修改版
2018/03/13 Python
python3 kubernetes api的使用示例
2021/01/12 Python
详解使用scrapy进行模拟登陆三种方式
2021/02/21 Python
HTML5新增form控件和表单属性实例代码详解
2019/05/15 HTML / CSS
皇马官方商城:Real Madrid Store
2016/09/02 全球购物
精油和天然健康美容产品:Art Naturals
2018/01/27 全球购物
StringBuilder和String的区别
2015/05/18 面试题
汽车维修与检测专业应届生求职信
2013/11/12 职场文书
实习生自荐信范文
2013/11/13 职场文书
生产车间主管岗位职责
2013/12/28 职场文书
在校生自我鉴定
2014/01/23 职场文书
离职报告范文
2014/11/04 职场文书
2014年度考核工作总结
2014/12/24 职场文书
金陵十三钗观后感
2015/06/04 职场文书
2015年中秋寄语
2015/07/31 职场文书
2019年教师节祝福语精选,给老师送上真诚的祝福
2019/09/09 职场文书