[Vue] : 动画

Vue中的动画

Vue中的动画,包括:

  • 4个时间点
    • v-enter: 定义进入过渡的开始状态。
    • v-enter-to: 定义进入过渡的结束状态。
    • v-leave: 定义离开过渡的开始状态。
    • v-leave-to: 定义离开过渡的结束状态。
  • 2个时间段
    • v-enter-active: 定义进入过渡生效时的状态。
    • v-leave-active: 定义离开过渡生效时的状态。

典型示例:

  • html,使用 transition 将需要过渡的元素包裹起来
<div id="app">
    <input type="button" value="切换" @click="flag = !flag">
    <transition>
        <h3 v-if="flag">这是一个H3</h3>
    </transition>
</div>
  • javascript
var vm = new Vue({
    el: '#app',
    data: {
        flag: false
    }
})
  • css
/* 定义进入过渡的开始状态 和 离开过渡的结束状态 */
.v-enter,
.v-leave-to {
    opacity: 0;
}

/* 定义进入和离开时候的过渡状态 */
.v-enter-active,
.v-leave-active {
    transition: all 0.4s ease;
}

自定义v-前缀

默认transcition元素自动使用v-样式,通过name属性可以自定义样式前缀

<transition name="my">
	<h3 v-if="flag2">这是一个H3</h3>
</transition>
.my-enter,
.my-leave-to {
    opacity: 0;
    transform: translateX(150px)
}

.my-enter-active,
.my-leave-active {
    transition: all 0.4s ease
}

使用第三方 CSS 动画库

  1. 导入动画类库:
<link rel="stylesheet" type="text/css" href="./lib/animate.css">
  1. 定义 transition 及属性:
  • enter-active-class定义入场动画,leave-active-class定义离开动画,注意css样式还要加上animated才生效
<transition enter-active-class="animated bounceIn" leave-active-class="animated bounceOut">
	<h3 v-if="flag">这是一个H3</h3>
</transition>
  • animated样式也可以挂在内部元素上
<transition enter-active-class="bounceIn" leave-active-class="bounceOut">
    <h3 v-if="flag" class="animated">这是一个H3</h3>
</transition>
  • :duration=“毫秒值” 统一指定进入和离开的动画时长
<transition enter-active-class="bounceIn" leave-active-class="bounceOut" :duration="500">
    <h3 v-if="flag" class="animated">这是一个H3</h3>
</transition>
  • :duration="{ enter: 200, leave: 400 }" 分别指定进入和离开的动画时长
<transition enter-active-class="bounceIn" leave-active-class="bounceOut" :duration="{ enter: 200, leave: 400 }">
    <h3 v-if="flag" class="animated">这是一个H3</h3>
</transition>

使用动画钩子函数

可以在属性中声明钩子函数

<transition
  v-on:before-enter="beforeEnter"
  v-on:enter="enter"
  v-on:after-enter="afterEnter"
  v-on:enter-cancelled="enterCancelled"

  v-on:before-leave="beforeLeave"
  v-on:leave="leave"
  v-on:after-leave="afterLeave"
  v-on:leave-cancelled="leaveCancelled"
>
  <!-- ... -->
</transition>
// ...
methods: {
  // --------
  // 进入中
  // --------

  beforeEnter: function (el) {
    // ...
  },
  // 当与 CSS 结合使用时
  // 回调函数 done 是可选的
  enter: function (el, done) {
    // ...
    done()
  },
  afterEnter: function (el) {
    // ...
  },
  enterCancelled: function (el) {
    // ...
  },

  // --------
  // 离开时
  // --------

  beforeLeave: function (el) {
    // ...
  },
  // 当与 CSS 结合使用时
  // 回调函数 done 是可选的
  leave: function (el, done) {
    // ...
    done()
  },
  afterLeave: function (el) {
    // ...
  },
  // leaveCancelled 只用于 v-show 中
  leaveCancelled: function (el) {
    // ...
  }
}

定义半场动画示例:

  • 动画钩子函数的第一个参数:el,表示 要执行动画的那个DOM元素,是个原生的 JS DOM对象,可以认为 , el 是通过document.getElementById('')方式获取到的原生JS DOM对象
  • beforeEnter 表示动画入场之前,此时,动画尚未开始,可以 在 beforeEnter 中,设置元素开始动画之前的起始样式
  • enter 表示动画 开始之后的样式
  • 动画完成之后,会调用 afterEnter

当只用 JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调。否则会产生动画延迟现象。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="lib/vue-2.4.0.js"></script>
  <link rel="stylesheet" href="./lib/animate.css">
  <style>
    .ball {
      height: 20px;
      width: 20px;
      background-color: red;
      border-radius: 50%;
    }
  </style>
</head>

<body>
  <div id="app">
    <input type="button" value="移动" @click="flag = !flag">
    <transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
      <div class="ball" v-if="flag"></div>
    </transition>
  </div>

  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        flag: false
      },
      methods: {
        beforeEnter(el) {
          // 设置小球开始动画之前的,起始位置
          el.style.transform = "translate(0, 0)"
        },
        enter(el, done) {
          // 这句话,没有实际的作用,但是,如果不写,出不来动画效果;
          // 可以认为 el.offsetWidth 会强制动画刷新,也可以写成offsetHeight,offsetLeft,offsetTop
          el.offsetWidth
          // 设置小球完成动画之后的,结束状态
          el.style.transform = "translate(150px, 450px)"
          el.style.transition = "all 0.5s ease"
          // 这里的 done, 起始就是 afterEnter 这个函数,也就是说:done 是 afterEnter 函数的引用
          done()
        },
        afterEnter(el) {
          this.flag = !this.flag
        }
      }
    })
  </script>
</body>

</html>

v-for 的列表过渡

  1. 定义过渡样式:
  • 在实现列表过渡的时候,如果需要过渡的元素,是通过v-for循环渲染出来的,不能使用transition 包裹,需要使用transition-group
  • 如果要为v-for循环创建的元素设置动画,必须为每一个 元素 设置:key 属性
  • transition-group 添加appear属性,实现页面刚展示出来时候,入场时候的效果
  • 过 为transition-group元素,设置tag属性,指定transition-group渲染为指定的元素,如果不指定tag属性,默认,渲染为span标签。
  • <transition-group> 组件还有一个特殊之处。不仅可以进入和离开动画,还可以改变定位。要使用这个新功能只需了解新增的 v-move 特性,它会在元素的改变定位的过程中应用
  • v-movev-leave-active 结合使用,能够让列表的过渡更加平缓柔和:
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="lib/vue-2.4.0.js"></script>
  <style>
    li {
      border: 1px dashed #999;
      margin: 5px;
      list-style: none;
      line-height: 35px;
      padding-left: 5px;
      font-size: 12px;
      width: 100%;
    }

    li:hover {
      background-color: pink;
      transition: all 0.4s ease;
    }

    .v-enter,
    .v-leave-to {
      opacity: 0;
      transform: translateY(80px);
    }

    .v-enter-active,
    .v-leave-active {
      transition: all 0.6s ease;
    }
	
    /* 下面的 .v-move 和 .v-leave-active 配合使用,能够实现列表后续的元素,渐渐地漂上来的效果 */
    .v-move {
      transition: all 0.6s ease;
    }
	/* 同时指定li width: 100% */
    .v-leave-active {
      position: absolute;
    }
  </style>
</head>

<body>
  <div id="app">
    <div>
      <label>
        id:
        <input type="text" v-model="id">
      </label>
      <label>
        name:
        <input type="text" v-model="name">
      </label>
      <input type="button" value="添加" @click="add">
    </div>

    <transition-group appear tag="ul">
      <li v-for="(user, i) in list" :key="user.id" @click="del(i)">
        {{user.id}} -- {{user.name}}
      </li>
    </transition-group>
  </div>

  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        id: '',
        name: '',
        list: [
          { id: 1, name: "张三1" },
          { id: 2, name: "张三2" },
          { id: 3, name: "张三3" },
          { id: 4, name: "张三4" },
          { id: 5, name: "张三5" },
        ]
      },
      methods: {
        add() {
          this.list.push({ id: this.id, name: this.name })
          this.id = this.name = ''
        },
        del(i) {
          this.list.splice(i, 1)
        }
      }
    })
  </script>
</body>

</html>
posted @ 2019-06-24 00:15  moon1992  阅读(246)  评论(0编辑  收藏  举报