zoukankan      html  css  js  c++  java
  • Vue列表过渡

    前面的话

      本文将详细介绍Vue列表过渡

    概述

      前面分别介绍了单元素CSS过渡JS过渡,以及多元素过渡。如何同时渲染整个列表呢?在这种情景中,需要使用<transition-group>组件

    【<transition-group>】

      <transition-group>不同于 <transition>, 它会以一个真实元素呈现:默认为一个 <span>。也可以通过 tag 特性更换为其他元素。而且其内部元素总是需要提供唯一的 key 属性值

    <transition-group name="list" tag="p">
        <!-- ... -->
      </transition-group>

    普通过渡

      下面是一个添加和删除列表项的例子

    <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="list-demo" class="demo">
      <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>
    <script>
    new Vue({
      el: '#list-demo',
      data: {
        items: [1,2,3,4,5,6,7,8,9],
        nextNum: 10
      },
      methods: {
        randomIndex() {
          return Math.floor(Math.random() * this.items.length)
        },
        add() {
          this.items.splice(this.randomIndex(), 0, this.nextNum++)
        },
        remove() {
          this.items.splice(this.randomIndex(), 1)
        },
      }
    })
    </script>

    平滑过渡

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

    【v-move】

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

      在上面代码中基础上,做出如下改进:

      1、增加.list-move的样式,使元素在进入时实现过渡效果

      2、在.list-leave-active中设置绝对定位,使元素在离开时实现过渡效果

    <style>
    .list-item {display: inline-block;margin-right: 10px;}
    .list-move,.list-enter-active, .list-leave-active {transition: 1s;}
    .list-leave-active{position:absolute;}
    .list-enter, .list-leave-to{opacity: 0;transform: translateY(30px);}
    </style>

    变换过渡

      下面接着利用move属性,进行变换过渡,即一个列表中的列表项既不增加也不减少,只是不断地变换其位置

    <style>
    .list-move{transition: transform 1s;}
    </style>
    <div id="list-demo" class="demo">
      <button @click="shuffle">shuffle</button>
      <transition-group name="list" tag="ul">
        <li v-for="item in items" :key="item">{{item}}</li>
      </transition-group>
    </div>
    <script>
    new Vue({
      el: '#list-demo',
      data: {
        items: [1,2,3,4,5,6,7,8,9],
      },
      methods: {
        shuffle(){
          this.items = this.items.sort(()=>{return Math.random() - 0.5;})
        },
      }
    })
    </script>

      下面的效果看起来很神奇,内部的实现,Vue 使用了一个叫 FLIP 简单的动画队列,使用 transforms 将元素从之前的位置平滑过渡新的位置

      下面将进入离开的例子和这个技术结合, 使列表的一切变动都会有动画过渡

      [注意]使用 FLIP 过渡的元素不能设置为 display: inline 。作为替代方案,可以设置为 display: inline-block 或者放置于 flex 中

    <style>
    .list-item {display: inline-block;margin-right: 10px;}
    .list-move,.list-enter-active, .list-leave-active {transition: 1s;}
    .list-leave-active{position:absolute;}
    .list-enter, .list-leave-to{opacity: 0;transform: translateY(30px);}
    </style>

      以上代码中,由于move、enter和leave都需要设置transition。因此,直接在元素上设置transition即可

    <style>
    .list-item {display: inline-block;margin-right: 10px;transition: 1s;}
    .list-leave-active{position:absolute;}
    .list-enter, .list-leave-to{opacity: 0;transform: translateY(30px);}
    </style>

      下面是完整代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    .list-item {display: inline-block;margin-right: 10px;transition: 1s;}
    .list-leave-active{position:absolute;}
    .list-enter, .list-leave-to{opacity: 0;transform: translateY(30px);}
    </style>
    </head>
    <body>
    <div id="list-demo" class="demo">
      <button @click="shuffle">shuffle</button>
      <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>
    <script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/26/ddzmgynp/vue.js"></script>
    <script>
    new Vue({
      el: '#list-demo',
      data: {
        items: [1,2,3,4,5,6,7,8,9],
        nextNum: 10
      },
      methods: {
        randomIndex() {
          return Math.floor(Math.random() * this.items.length)
        },
        add() {
          this.items.splice(this.randomIndex(), 0, this.nextNum++)
        },
        remove() {
          this.items.splice(this.randomIndex(), 1)
        },    
        shuffle(){
          this.items = this.items.sort(()=>{return Math.random() - 0.5;})
        },
      }
    })
    </script>
    </body>
    </html>

    多维列表

      FLIP 动画不仅可以实现单列过渡,多维网格的过渡也同样简单

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    .container {width: 270px;margin-top: 10px;line-height:30px;text-align:center;}
    .cell {display: inline-block;width: 30px;height: 30px;outline: 1px solid #aaa;}
    .cell-move {transition:1s;}
    </style>
    </head>
    <body>
    <div id="list-demo" class="demo">
      <button @click="shuffle">shuffle</button>
      <transition-group name="cell" tag="div" class="container">
        <span v-for="cell in cells" :key="cell.id" class="cell">{{ cell.number }}</span>
      </transition-group>
    </div>
    <script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/26/ddzmgynp/vue.js"></script>
    <script>
    new Vue({
      el: '#list-demo',
       data: {
          cells: Array.apply(null, { length: 81 })
            .map(function (_, index) { 
              return {
                id: index,
                number: index % 9 + 1
              }
            })
        },
      methods: {
        shuffle(){
          this.cells = this.cells.sort(()=>{return Math.random() - 0.5;})
        },
      }
    })
    </script>
    </body>
    </html>

    渐进过渡

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

      下面是使用CSS过渡实现的一个例子

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    .list-move,.list-enter-active, .list-leave-active {transition: 1s;}
    .list-leave-active{position:absolute;}
    .list-enter,.list-leave-to{opacity: 0;height:0;}
    </style>
    </head>
    <body>
    <div id="list-demo" class="demo">
      <input v-model="query">
      <transition-group name="list" tag="ul">
        <li v-for="(item, index) in computedList" :key="item" :data-index="index">{{item}}</li>
      </transition-group>
    </div>
    <script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/26/ddzmgynp/vue.js"></script>
    <script>
    new Vue({
      el: '#list-demo',
      data: {
        query: '',
        list: ['HTML','CSS','Javascript','jQuery','Vue']
      },
      computed: {
        computedList() {
          return this.list.filter((item)=>{
            return item.toLowerCase().indexOf(this.query.toLowerCase()) !== -1
          })
        }
      },  
    })
    </script>
    </body>
    </html>

      上面的效果中,列表项是一齐运动的。如果要实现依次运动的效果,则需要使用JS过渡来实现

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Document</title>
    </head>
    <body>
    <div id="list-demo" class="demo">
      <input v-model="query">
      <transition-group name="list" tag="ul" :css="false" @before-enter="beforeEnter" @enter="enter" @leave="leave">
        <li v-for="(item, index) in computedList" :key="item" :data-index="index">{{item}}</li>
      </transition-group>
    </div>
    <script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/26/ddzmgynp/velocity.min.js"></script>
    <script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/26/ddzmgynp/vue.js"></script>
    <script>
    new Vue({
      el: '#list-demo',
      data: {
        query: '',
        list: ['HTML','CSS','Javascript','jQuery','Vue']
      },
      computed: {
        computedList() {
          return this.list.filter((item)=>{
            return item.toLowerCase().indexOf(this.query.toLowerCase()) !== -1
          })
        }
      },  
      methods: {
        beforeEnter(el) {
          el.style.opacity = el.style.height = 0
        },
        enter(el, done) {
          setTimeout(()=>{
            Velocity(el,{ opacity: 1, height: '1.6em' },{ complete: done })
          }, el.dataset.index * 150)
        },
        leave(el, done) {
          setTimeout(()=>{
            Velocity(el,{ opacity: 0, height: 0 },{ complete: done })
          }, el.dataset.index * 150)
        }
      },  
    })
    </script>
    </body>
    </html>

  • 相关阅读:
    __ATTRIBUTE__ 你知多少?【转】
    mount源码分析 【转】
    linux下共享内存mmap和DMA(直接访问内存)的使用 【转】
    mmap DMA【转】
    内存映射MMAP和DMA【转】
    进度条,随机数---demo笔记【原创】
    Linux内核抢占与中断返回【转】
    内核随记(三)--同步(1)【转】
    内核随记(三)--同步(2)【转】
    理解Linux中断 (1)【转】
  • 原文地址:https://www.cnblogs.com/xiaohuochai/p/7412798.html
Copyright © 2011-2022 走看看