Vue实现过渡动画的三种方式

  • Post author:
  • Post category:vue





Vue 在插入、更新或者移除DOM 时,提供多种不同方式的应用过渡效果。包括以下方式:


  • 使用vue的transition标签结合css样式完成动画
  • 利用animate.css结合transition实现动画
  • 利用 vue中的钩子函数实现动画




一、使用vue的transition标签结合css样式完成动画




1、给需要运动的元素加入transition标签




<transition>


需要运动的元素


</transition>


2、默认情况下如果控制了transition标签元素的显示和隐藏它会默认给这个元素加入一些class



隐藏:加入类名:


v-leave





定义离开过渡的开始状态




v-leave-active :


定义离开过渡生效时的状态。


v-leave-to :


定义离开过渡的结束状态。



显示:加入类名:


v-enter:


准备进行运动的状态(起始状态)

​​​​​​​

v-enter-active:


整个运动状态

​​​​​​​

v-enter-to:


整个运动状态(强调运动的结果,结束状态)


3、将来如果给transition设置一个name为“show”以后,将来所有的类的名称都需要改变,默认前缀为v- 如果加入了name属性,需要将v- 改为show-


示例:

    <style>
      .fade-enter-active, .fade-leave-active {
          transition: opacity .5s;
       }
      .fade-enter, .fade-leave-to{
          opacity: 0;
       }
    </style>
    <div id="demo">
        <button v-on:click="show = !show">
          Toggle
        </button>
        <transition name="fade">
          <p v-if="show">hello</p>
        </transition>
    </div>
    <script>
        new Vue({
            el: '#demo',
            data: {
                show: true
            }
        })
    </script>




当插入或删除包含在






transition






组件中的元素时,Vue 将会做以下处理:



(1)自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名。


(2)如果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用。


(3)如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作 (插入/删除) 在下一帧中立即执行。(注意:此指浏览器逐帧动画机制,和 Vue 的 nextTick 概念不同)


对于这些在过渡中切换的类名来说,如果使用一个没有名字的


<transition>


,则


v-


是这些类名的默认前缀。如果你使用了


<transition name=”my-transition”>


,那么


v-enter


会替换为


my-transition-enter




v-enter-active





v-leave-active


可以控制进入/离开过渡的不同的缓和曲线




二、利用animate.css结合transition实现动画


可以通过以下 attribute 来自定义过渡类名:


enter-class


enter-active-class


enter-to-class (2.1.8+)


leave-class


leave-active-class


leave-to-class (2.1.8+)

它们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库,如

Animate.css

结合使用十分有用。

<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
    <div id="example-3">
        <button @click="show = !show">
          Toggle render
        </button>
        <transition
          name="custom-classes-transition"
          enter-active-class="animated tada"
          leave-active-class="animated bounceOutRight"
        >
           <p v-if="show">
            明月几时有,把酒问青天。
           </p>
        </transition>
    </div>
    <script>
        new Vue({
            el: '#example-3',
            data: {
                show: true
            }
        })
    </script>


三、利用 vue中的钩子函数实现动画

<style>
        .show {
           transition: all 0.5s;
        }
    </style>
    <div id="app">
        <button @click="toggle">显示/隐藏</button><br>
        <transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
            <div class="show"  v-show="isshow">
                明月几时有?把酒问青天
            </div>
        </transition>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
              isshow: false
            },
            methods: {
               toggle: function () {
                  this.isshow = !this.isshow;
            },
            beforeEnter: function (el) {
                console.log("beforeEnter");
                 // 当入场之前会执行 v-enter
                 el.style = "padding-left:100px";
             },
            enter: function (el, done) {
                // 当进行的过程中每执行 v-enter-active
                console.log("enter");
              // 为了能让代码正常进行,在设置了结束状态后必须调用一下这个元素的
              // offsetHeight / offsetWeight  只是为了让动画执行
                el.offsetHeight;
                // 结束的状态最后写在enter中
                el.style = "padding-left:0px";
                // 执行done继续向下执行
                 done();
            },
            afterEnter: function (el) {
                // 当执行完毕以后会执行
                console.log("afterEnter");
                 //this.isshow = false;
             }
         }
     }) 
    </script>




四、综合案例




1、View代码

<div id="app">
        <div class="add">
            编号: <input id="id" v-color="color" v-focus type="text" v-model="id">
            品牌名称: <input v-model="name" type="text">
            <button @click="add">添加</button>
        </div>
        
        <div>
            <table class="tb">
                <tr>
                    <th>编号</th>
                    <th>品牌名称</th>
                    <th>创立时间</th>
                    <th>操作</th>
                </tr>
                <tr v-if="list.length <= 0">
                    <td colspan="4">没有品牌数据</td>
                </tr>
                <!--加入: key="index" 时候必须把所有参数写完整  -->
                <tr v-for="(item,key,index) in list" :key="index">
                    <td>{{item.id}}</td>
                    <td>{{item.name}}</td>
                    <td>{{item.ctime | dateFrm("/")}}</td>
                    <!-- 使用vue来注册事件时,我们在dom元素中是看不到的 -->
                    <td><a href="javascript:void(0)" @click="del(item.id)">删除</a></td>
                </tr>
            </table>
        </div>

        <transition
            @before-enter="beforeEnter"
            @enter="enter"
            @after-enter ="afterEnter"
            @before-leave="beforeLeave"
            @leave="leave"
            @after-leave ="afterLeave"
        >
            <div class="del" v-show="isshow">
                <ul>
                    <li>您确定要删除当前数据吗</li>
                    <li>
                        <button @click="delById">确定</button>
                        <button @click="showClose">关闭</button>
                    </li>
                </ul>
            </div>
        </transition>
    </div>


2、

Model代码

// 使用全局过滤器(公有过滤器)
    Vue.filter("dateFrm", function (time,spliceStr) {
        // return "2017-11-16";
        var date = new Date(time);
        //得到年
        var year = date.getFullYear();
        // 得到月
        var month = date.getMonth() + 1;
        // 得到日
        var day = date.getDate();
        return year + spliceStr + month + spliceStr + day;
    });
    // 先将自定义指令定义好
    // directive有两个参数
    //参数一: 自定义指令 v-focus
    //参数二: 对象,对象中可以添加很多方法
    // 添加一个inserted方法:而这个方法中又有两个参数:
    //参数一:el 当前使用自定义指令的对象
    //参数二:obj 是指它(v-color="color" )后面设置的表达式
    //{expression:"color",value:"red",}
    Vue.directive("focus", {
        inserted: function (el, obj) {
            // console.log(el);
            el.focus();
        }
    });
    Vue.directive("color", {
        inserted: function (el, obj) {
            // obj.style.color = "red";
            obj.style.color = obj.value;//????????????
            console.log(obj.value);
        }
    });
    var vm = new Vue({
        el: "#app",
        data: {
            delId:"",// 用来将要删除数据的id进行保存
            isshow:false,
            color: "green",
            id: 0,
            name: '',
            list: [
                { "id": 1, "name": "德云IT学苑", "ctime": Date() },
                { "id": 2, "name": "西安邮电大学", "ctime": Date() }
            ]
        },
        // mounted(){
        //     this.getFocus()
        // },
        methods: {
            add: function () {
                //将id和namepush到list数组中
                this.list.push({ "id": this.id, "name": this.name, "ctime": Date() });
            },
            del: function (id) {
                this.isshow = true;
                // 将得到的id保存到delId里面
                this.delId = id;
            },
            beforeEnter:function(el) {
                el.style.left = "100%";
            },
            enter:function(el,done) {
                el.offsetHeight;
                el.style.left = "35%";
            },
            afterEnter:function(el){
            },
            beforeLeave:function(el){
                el.style.left = "35%";
            },
            leave:function(el,done){
                el.offsetHeight;
                el.style.left = "100%";
                setTimeout(function(){
                    done();
                },500);
            },
            afterLeave:function(el){
            },
            showClose:function(el){
                this.isshow = false;
            },
            delById:function() {
                _this = this;
                // 根据DelId删除对应的数据
                 var index = this.list.findIndex(function(item){
                    return item.id ==_this.delId;
                });
                this.list.splice(index,1);
                // 关闭删除框
                this.isshow = false;
            }
        }
    });

3


、CSS代码

#app {
            width: 600px;
            margin: 10px auto;
        }

        .tb {
            border-collapse: collapse;
            width: 100%;
        }
        .tb th {
            background-color: #0094ff;
            color: white;
        }
        .tb td,
        .tb th {
            padding: 5px;
            border: 1px solid black;
            text-align: center;
        }
        .add {
            padding: 5px;
            border: 1px solid black;
            margin-bottom: 10px;
        }
        .del li{
        list-style: none;
        padding: 10px;
      }
    .del{
        position: absolute;
        top:45%;
        left: 45%;
        width: 300px;
        border: 1px solid rgba(0,0,0,0.2);
        transition: all 0.5s;
    }



版权声明:本文为m0_37911706原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。