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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

上庸者-不服周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值