Vue动画与生命周期详解

时间:2022-06-26
本文章向大家介绍Vue动画与生命周期详解,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

1.vue普通动画

Vue为vue动画提供的六个类: transition标签的name-enter, transition标签的name-leave 动画开始前动画元素的初始状态的 transition标签的name-enter-to, transition标签的name-leave-to 动画结束时元素的状态 transition标签的name-enter-active, transition标签的name-leave-active 动画的过渡状态

当动画从显示状态变为隐藏状态时,leave相关的类反之enter相关的类

需要做动画的元素必须用transition标签包裹起来.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue动画</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <style type="text/css">
        .hidden-enter-active, .hidden-leave-active{
            transition: .5s all;
        }
        .hidden-enter, .hidden-leave-to{
            opacity: 0;
            transform: translate(100px,20px);
        }
</style>
</head>
<body>
    <div id="app">
        <button @click="show=!show">点击动画</button>
        <transition name="hidden">
            <p v-if="show">Hello, Vue!</p>
        </transition>
    </div>
    <script type="text/javascript">
        let app =new Vue({
           el:'#app',
           data:{
               show:true
           },
        });
</script>
</body>
</html>

2.关键帧动画

示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>关键帧动画</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <style type="text/css">
        p{
            width: 100px;
            height: 100px;
            margin-top: 50px;
            /*background-color: yellow;*/
        }
        @keyframes bounce {
            0%{
                transform: scale(1,1);
                opacity: 1;
            }
            50%{
                transform: scale(2,2);
                opacity: 0.5;
            }
            100%{
                transform: scale(0,0);
                opacity: 0;
            }
        }
        .hs-enter-active{
            animation: bounce 2s reverse;
        }
        .hs-leave-active{
            animation: bounce 2s;
        }
</style>
</head>
<body>
    <div id="app">
        <button @click="show=!show">关键帧动画</button>
        <transition name="hs">
            <p v-if="show">Hello, Vue!</p>
        </transition>
    </div>
    <script type="text/javascript">
        let app =new Vue({
            el:'#app',
            data:{
                show:true
            },
        });
</script>
</body>
</html>

3. 第三方动画

需要引入animate.css文件

需要在transition标签里,此时他有两个类 enter-active-class 和 leave-active-class,他们的值为动画的名字.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>第三方动画</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
    <style type="text/css">
        .p1{
            animation-duration: 2s;
        }
</style>
</head>
<body>
    <div id="app">
        <h2 class="animated swing">这是h2组件</h2>
        <button @click="show=!show">第三方动画</button>
        <transition enter-active-class="animated bounce" leave-active-class="animated zoomOutRight">
            <p v-if="show" class="p1">Hello, Vue!</p>
        </transition>
    </div>
    <script type="text/javascript">
        let app =new Vue({
            el:'#app',
            data:{
                show:true
            },
        });
</script>
</body>
</html>

4.多个元素过渡动画

同时生效的进入和离开的过渡不能满足所有要求,所以 Vue提供了过渡模式 in-out:新元素先进行过渡,完成之后当前元素过渡离开。 out-in:当前元素先进行过渡,完成之后新元素过渡进入。

当有相同标签名的元素切换时,需要通过 key 特性设置唯一的值来标记以让 Vue 区分它们,否则 Vue 为了效率只会替换相同标签内部的内容。即使在技术上没有必要,给在 <transition> 组件中的多个元素设置 key 是一个更好的实践。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>多个元素过渡动画</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
</head>
<body>
    <div id="app">
        <button @click="show=!show">点击</button>
        <transition enter-active-class="animated bounce" leave-active-class="animated bounce" mode="out-in">
            <p class="p1" key="0" v-if="show">第一个p标签</p>
            <p class="p2" key="1" v-else>第二个p标签</p>
        </transition>
    </div>
    <script type="text/javascript">
        let app =new Vue({
            el:'#app',
            data:{
                show:true
            },
        });
</script>
</body>
</html>

5.多个组件过渡动画

component组件,系统定义好的组件: 作用: 根据is属性值的变化,动态显示对应的组件,is属性值是想要显示的组件名

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>多个组件过渡动画</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
    <style type="text/css">
        @keyframes show {
            0%{
                opacity: 1;
             }
            50%{
                opacity: 0.5;
            }
            100%{
                opacity: 1;
            }
        }
        .cmp-leave-active{
            animation: show 0.5s;
        }
        .cmp-enter-active{
            animation: show 0.5s reverse;
        }
</style>
</head>
<body>
    <div id="app">
        <button @click="view='child1'">组件一</button>
        <button @click="view='child2'">组件二</button>
        <transition mode="out-in" name="cmp">
            <component :is="view"></component>
        </transition>
    </div>
    
    <template id="child1">
        <fieldset>
            <legend><h2>这是child1组件</h2></legend>
            <h3>这是child1标题</h3>
            <p>这是child1内容</p>
        </fieldset>
    </template>
    <template id="child2">
        <fieldset>
            <legend><h2>这是child2组件</h2></legend>
            <input type="text" placeholder="请输入用户名">
            <input type="text" placeholder="请输入密码">
            <button>登录</button>
        </fieldset>
    </template>
    <script type="text/javascript">
        let child1 = {
            template:'#child1'
        };
        let child2 = {
            template:'#child2'
        };
        
        let app =new Vue({
            el:'#app',
            data:{
                view:'child1'
            },
            components:{
                child1,
                child2
            }
        });
</script>
</body>
</html>

6.生命周期钩子

  • 什么是生命周期:从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期!
  • 生命周期钩子:就是生命周期事件的别名而已;
  • 生命周期钩子 = 生命周期函数 = 生命周期事件
  • 主要的生命周期函数分类:
  • 创建期间的生命周期函数:
    • created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板
    • beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中
    • mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示
    • beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
  • 运行期间的生命周期函数:
    • updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!
    • beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
  • 销毁期间的生命周期函数:
    • destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
    • beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>生命周期钩子</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <button @click="count++">点击</button>
        <h1 id="el_h1">{{msg}}--{{count}}</h1>
    </div>
    <script type="text/javascript">
        let app =new Vue({
            el:'#app',
            data:{
                msg:"生命周期钩子",
                count:0
            },
            methods:{},
            beforeCreate(){
                //不能获取data数据
                console.log("beforeCreate触发!"+this.msg)
            },
            created(){
                //初始化完毕,可以获取data数据
                console.log("created触发!"+this.msg)
            },
            beforeMount(){
                //this有,但是DOM还没有创建好,所以标签里的大括号没有被替换成真正的值
                console.log("beforeMount触发!",el_h1)
            },
            mounted(){
                //DOM已经挂载完毕,准备就绪, {{}}里的值也替换完毕
                console.log("mounted触发!",el_h1)
            },
            beforeUpdate(){
                //data数据已经修改,但是因为此时DOM还没有更新,页面内容还没有修改
                console.log("beforeUpdate触发!",this.count,el_h1.innerHTML)
            },
            updated(){
                //data数据和页面内容都已修改完毕
                console.log("updated触发!",this.count,el_h1.innerHTML)
            },
            beforeDestroy(){
                console.log("beforeDestroy触发!")
            },
            destroyed(){
                console.log("destroyed触发!")
            }
        });
        
        setTimeout(()=>{
            app.$destroy();
        },2000);
</script>
</body>
</html>

附: