(六)VUE动画

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

  • 在 CSS 过渡和动画中自动应用 class;
  • 可以配合使用第三方 CSS 动画库,如 Animate.css;
  • 在过渡钩子函数中使用 JavaScript 直接操作 DOM;
  • 可以配合使用第三方 JavaScript 动画库,如 Velocity.js;

   Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡动画:

  • 条件渲染 (使用 v-if)
  • 条件展示 (使用 v-show)
  • 动态组件
  • 组件根节点

1、过渡类名实现动画

   在进入/离开的过渡中,会有 6 个 class 切换。

  • v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。

  • v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。

  • v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。

  • v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。

  • v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。

  • v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。

   如果 <transition>中没有使用 name 属性,则 v- 是这些类名的默认前缀。如果使用了 <transition name=“my”>,那么 v-enter 会替换为 my-enter。

  • 示例代码:
<!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="../vue.min.js"></script>
    <style>
        .v-enter,.v-leave-to {
            opacity: 0;
            transform: translateX(80px);
        }

        .v-enter-active, .v-leave-active{
            transition: all 0.4s ease;
        }
        
        /** 自定义v-前缀 **/
        .my-enter,.my-leave-to {
            opacity: 0;
            transform: translateY(150px);
        }

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


    </style>
</head>
<body>
    <div id="app">
        <input type="button" value="v-前缀" @click="flag=!flag">

        <transition>
            <p v-if="flag">This is a Content1.</p>
        </transition>

        <input type="button" value="my-前缀" @click="flag2=!flag2">

        <transition name="my">
            <p v-if="flag2">This is a Content2.</p>
        </transition>
        
    </div>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                flag: true,
                flag2: true,
            }
        })
    </script>
</body>
</html>

2、第三方类库实现动画

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

  • 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 结合使用十分有用。

   animate.css 是一个使用CSS3的animation制作的动画效果的CSS集合,里面预设了很多种常用的动画,且使用非常简单。

  • 示例代码:
<!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="../vue.min.js"></script>
    <link rel="stylesheet" href="../animate.css">
<body>
    <div id="app">
        <input type="button" value="show" @click="flag=!flag">

        <!-- 在duration属性可以一起设置动画时长,也可以使用对象分别设置 -->
        <transition 
        enter-active-class="bounceIn" 
        leave-active-class="bounceOut" 
        :duration="{enter: 200, leave: 400}">
            <!-- 在引用animate.css里的动画样式时,需要增加一个class--animated -->
            <p v-if="flag" class="animated">This is a Content1.</p>
        </transition>
        
    </div>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                flag: true,
            }
        })
    </script>
</body>
</html>

3、钩子函数实现半场动画

   可以在<transition>的属性中声明 JavaScript 钩子,类似于事件处理:

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

   在Vue实例中具体实现 JavaScript 钩子函数:

methods: {
  // 动画进入前
  // el 执行动画的DOM元素
  beforeEnter: function (el) {
    // ...
  },
  // 动画进入时
  // 回调函数 done 是可选的 表示立即执行afterEnter()函数
  enter: function (el, done) {
    // ...
    done()
  },
  // 动画进入后
  afterEnter: function (el) {
    // ...
  },
  enterCancelled: function (el) {
    // ...
  },
  
  // 动画离场前
  beforeLeave: function (el) {
    // ...
  },
  // 动画离场时
  leave: function (el, done) {
    // ...
    done()
  },
  // 动画离场后
  afterLeave: function (el) {
    // ...
  },
  // leaveCancelled 只用于 v-show 中
  leaveCancelled: function (el) {
    // ...
  }
}
  • 示例代码:
<!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="../vue.min.js"></script>
    <style>
        .ball {
            width: 15px;
            height: 15px;
            border-radius: 50%;
            background-color: red;
        }
    </style>
<body>
    <div id="app">
        <input type="button" value="show" @click="flag=!flag">

        <transition 
            @before-enter="beforeEnter" 
            @enter="enter" 
            @after-enter="afterEnter">
            <div class="ball" v-show="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
                    
                    el.style.transform = "translate(150px,450px)"
                    el.style.transition = 'all 1s ease'
                    done()
                },
                afterEnter(el){
                    this.flag = !this.flag
                }
            }
        })
    </script>
</body>
</html>

4、<transition-group>元素实现列表动画

   如果要同时渲染整个列表,比如在 v-for 这种场景中,可以使用 <transition-group> 组件,这个组件有以下特点:

  • 不同于 <transition>,它会以一个真实元素呈现:默认为一个 <span>,也可以通过 tag 特性更换为其他元素;
  • 过渡模式不可用,因为我们不再相互切换特有的元素;
  • 内部元素总是需要提供唯一的 key 属性值;
  • CSS 过渡的类将会应用在内部的元素中,而不是这个组/容器本身。

   <transition-group> 不仅可以设置进入和离开动画,还可以利用 v-move 特性改变定位。它会在元素的改变定位的过程中应用,对于设置过渡的切换时机和过渡曲线非常有用。

	// v-move 需要搭配 v-leave-active ,才能起作用
	.v-move{
		transition: all 0.6s ease;
	}
	.v-leave-active{
		position: absolute;
	}

   可以通过 <transition-group> 的 appear 特性设置节点在初始渲染的过渡。

	<transition appear>
	  <!-- ... -->
	</transition>
	
	<!-- 也可以自定义css类名 -->
	<transition
	  appear
	  appear-class="custom-appear-class"
	  appear-to-class="custom-appear-to-class" (2.1.8+)
	  appear-active-class="custom-appear-active-class"
	>
	  <!-- ... -->
	</transition>
  • 示例代码:
<!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="../vue.min.js"></script>
    <link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <style>
        li {
            border: 1px dashed #999;
            margin: 5px;
            line-height: 35px;
            padding-left: 5px;
            font-size: 12px;
            width: 100%;
        }
        li:hover {
            background-color: hotpink;
            transition: all 0.8s ease;
        }

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

        .v-enter-active, .v-leave-active{
            transition: all 0.6s ease;
        }

        .v-move{
            transition: all 0.6s ease;
        }
        .v-leave-active{
            position: absolute;
        }
    </style>
</head>
<body>
    <div id="app">
        <div class="panel panel-primary">
            <div class="panel-heading">
                <h3 class="panel-title">添加</h3>
            </div>

            <div class="panel-body form-inline">
                <label>
                    Id:
                    <input type="text" class="form-control" v-model="id">
                </label>
                <label>
                    <!-- 注册键盘回车事件 -->
                    Name:
                    <input type="text" class="form-control" v-model="name" @keyup.enter="add">
                </label>

                <input type="button" value="添加" class="btn btn-primary" @click="add">

            </div>
        </div>

        <!-- 通过tag将transition-group标签设为ul -->
        <transition-group appear tag="ul">
            <li v-for="item in list" :key="item.id" @click="del(item.id)">
                {{ item.id }} -- {{ item.name }}
            </li>
        </transition-group>
    </div>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                id: '',
                name: '',
                list: [
                    {id: 1, name: '奔驰'},
                    {id: 2, name: '宝马'},
                    {id: 3, name: '五菱'},
                ]
            },
            methods: {
                add: function(){
                    var car = {id: this.id, name: this.name}
                    this.list.push(car)
                    this.name = this.id = ''
                },
                del: function(id){
                    this.list.some((item, i) => {
                        if(item.id == id){
                            this.list.splice(i, 1)
                            return true
                        }
                    })

                }
            },
        })
    </script>
</body>
</html>

参考链接:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值