Vue动画过渡(四)

457 阅读3分钟

这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战

前言

今天来搞搞过渡动画,搞完这个过渡下一篇咋们就做个Todo案例,因为有用到这个知识点。然后这篇文章我们主要就讲解其中的一两个部分啊,包括单元素/组件的过渡列表的进入/离开过渡JavaScript 动画钩子;因为其实内容挺多的,更多内容还需要看官方文档的介绍。

单元素/组件的过渡

概念: Vue 在元素显示隐藏时, 提供了 transition 的封装组件,可以给任何元素和组件添加进入/离开过渡

语法:

<transition name="过渡css名">单一标签</transition>

栗子: 控制元素的显示与隐藏

<div id="app">
    <!--
    被transition标签包裹的元素在其显示隐藏时,六个不同的阶段会自动添加6class名
    元素进入的第一帧  [transition name 属性]-enter
    元素进入中        [transition name 属性]-enter-active
    元素进入的最后一帧 [transition name 属性]-enter-to
    元素离开的第一帧   [transition name 属性]-leave
    元素离开中        [transition name 属性]-leave-active
    元素离开的最后一帧 [transition name 属性]-leave-to
    -->
    <transition name="fade">
        <div class="box" v-if="show"></div>
    </transition>

    <button @click="show = !show">show/hidden</button>

</div>

<script>
    let vm = new Vue({
        el: '#app',
        data: {
            show: true
        }
    })
</script>

<style>
    .box {
        width: 100px;
        height: 100px;
        background-color: green;
    }

    .fade-enter,  .fade-leave-to{
        /*元素进入动画第一帧 类名*/
        opacity: 0;
        transform: translateX(300px);
        width: 0;
        height: 0;
    }

    .fade-enter-active, .fade-leave-active {
        /*元素进入整个过程中 类名*/
        transition: all .5s linear;
    }

    .fade-enter-to, .fade-leave {
        /*元素进入动画最后一帧 类名*/
        opacity: 1;
        transform: translateX(0);
        width: 100px;
        height: 100px;
    }
</style>

然后大概的效果就是这样,有了动画看起来就没有这么生硬的感觉。 a1.gif

注意:

  1. transition 标签内只能包含一个直接子元素

  2. transition 标签的name属性可以省略, 省略后元素进入离开时类名默认使用v-开头,例: v-enter,v-enter-to,v-leave,v-leave-to。

列表的进入/离开过渡

概念: 因为transition标签内部只能监听单个节点,或同一时间渲染多个节点中的一个。所以transition标签内部无法监听多个节点的。所以vue提供了 <transition-group> 组件事件内部监听多个节点的进入离开

语法:

<transition-group name="过渡css名">多个标签</transition-group>
<div id="app">
      <transition-group name="fade">
            <p v-for="c in arr" :key="c">{{c}}</p>
      </transion-group>
</div>

<script>
    let vm = new Vue({
        el: '#app',
        data: {
            arr: ['a', 'b', 'c', 'd', 'e']
        }
    })
</script>

<style>
    .fade-enter, 
    .fade-leave-to {
        transform: translateX(100px);
    }

    .fade-enter-active, 
    .fade-leave-active {
        transition: all .5s linear;
    }

    .fade-enter-to, 
    .fade-leave {
        transform: translateX(0);
    }
</style>

注意:

1、在transition-group组件中,列表渲染的key不能使用index。index作为key在添加或者删除时会导致不是正确> 的DOM节点被移除

2、transition-group会被vue默认渲染成一个span元素,如果你想设置transition-group组件渲染输出的节点可以设> 置其tag属性,例 tag="ul",transition-group组件就会被渲染成ul标签,参考如下代码和图示

// 主要看哦,我这里是设置了tag属性的为 ul的

<transition-group tag="ul" name="move">
        <li v-for="todo in todos" :key="todo.id">
           {{todo.text}}
        </li>
</transition-group>

接下来上图对比一哈 t1.png

t2.png

JavaScript 动画钩子

概念: 无论transition 和 transition-group 标签都支持使用动画js钩子。动画的钩子就是元素在整个动画过渡中默写特殊的时间点。当动画到达这些时间点时就会触发js钩子所绑定方法。有了js动画钩子就可以实现一些复杂的动画。

语法: 动画钩子就是vue提供的一些自定义事件,监听响应的事件触发绑定的函数

<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>

<transition-group
  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-group>

注意: 动画钩子事件会将当前动画元素作为参数传入到函数内部

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<div id="app">
    <transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
        <div v-show="show" class="box"></div>
    </transition>

    <button @click="show = !show">show/hidden</button>
</div>

<script>
    console.log(Velocity)
    new Vue({
        el: "#app",
        data: {
            show: true
        },
        methods: {
            beforeEnter(el) {
                console.log(el, '元素将要显示')
                el.style.opacity = 0
            },
            enter(el, done) {
                console.log('元素正在显示')
                Velocity(el, {
                    opacity: "1",
                    translateY: '30px',
                }, {
                    duration: 400,
                    easing: "swing",
                    loop: 2,
                    complete: done // 动画结束后触发done表示自定义动画结束
                });
            },
            afterEnter(el) {
                el.style.opacity = 1
                // console.log(el.offsetHeight)
                console.log('元素显示完毕')
            }
        }
    })
</script>

动画钩子事件会中enter事件与leave事件除了会默认传递第一个参数el(当前动画元素)以外,还会传递第二个参数 donedone 是一个方法用来告诉Vue当前元素的自定义动画已经结束,动画钩子才会执行下一步 after-enter 或者after-leave。如果自定义动画效果结束后不调用done可能会导致动画元素样式不更新

结尾

今天就先到这里啦!我们下期再见!码字不易,觉得不错的可以动动小指头点点赞啥的哟~

系列文章

Vue系列

Vue-Router系列

Vuex系列