Vue — transition实现过渡动画

前言

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

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

一、transition用法

<transition> 元素作为单个元素/组件的过渡效果。<transition> 只会把过渡效果应用到其包裹的内容上,而不会额外渲染 DOM 元素,也不会出现在可被检查的组件层级中。

当插入或删除包含在 <transition> 组件中的元素时,Vue 将会做以下处理:

  1. 自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名。
  2. 如果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用。
  3. 如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作 (插入/删除) 在下一帧中立即执行。(注意:此指浏览器逐帧动画机制,和 Vue 的 nextTick 概念不同)
<!-- 简单元素 -->
<transition>
    <div v-if="ok">toggled content</div>
</transition>
<!-- 动态组件 -->
<transition name="fade" mode="out-in" appear>
    <component :is="view"></component>
</transition>
<!-- 事件钩子 -->
<div id="transition-demo">
    <transition @after-enter="transitionComplete">
        <div v-show="ok">toggled content</div>
    </transition>
</div>


// 方法
methods: {
    transitionComplete(el) {
        // 传入'el'这个DOM元素作为参数。
    }
}

二、transition的属性

 常用属性:

  1. name: string,用于自动生成 CSS 过渡类名。例如:name: 'fade' 将自动拓展为 .fade-enter,.fade-enter-active 等。默认类名为 "v"
  2. appear: boolean,是否在初始渲染时使用过渡。默认为 false。
  3. css: boolean,是否使用 CSS 过渡类。默认为 true。如果设置为 false,将只通过组件事件触发注册的 JavaScript 钩子。
  4. type: string,指定过渡事件类型,侦听过渡何时结束。有效值为 "transition" 和 "animation"。默认 Vue.js 将自动检测出持续时间长的为过渡事件类型。
  5. mode: string,控制离开/进入过渡的时间序列。有效的模式有 "out-in" 和 "in-out";默认同时进行。
  6. duration: number | { enter: number, leave: number } 指定过渡的持续时间。默认情况下,Vue 会等待过渡所在根元素的第一个 transitionend 或 animationend 事件。

自定义过渡类名属性:
  1. enter-class: string
  2. leave-class: string
  3. appear-class: string
  4. enter-to-class: string
  5. leave-to-class: string
  6. appear-to-class: string
  7. enter-active-class: string
  8. leave-active-class: string
  9. appear-active-class: string

【1】过渡的类名

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

对于这些在过渡中切换的类名来说,如果你使用一个没有名字的 <transition>,则 v- 是这些类名的默认前缀。如果你使用了 <transition name="my-transition">,则以你设置的name值作为过渡类名前缀。例如:那么 v-enter 会替换为 my-transition-enter。

Transition Diagram

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 被删除),在过渡/动画完成之后移除。

【2】自定义过渡的类名

我们可以通过以下属性来自定义过渡类名,他们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库,如 Animate.css结合使用十分有用。

enter-class
enter-active-class
enter-to-class (2.1.8+)
leave-class
leave-active-class
leave-to-class (2.1.8+)
<!-- animate库 -->
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">

<!-- 过渡类名name -->
<!-- 自定义过渡类名enter-active-class、leave-active-class -->
<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">hello</p>
    </transition>
</div>

// js
data() {
    return {
        show: true
    }
}

三、transition的事件

<transition name="fade"
    @before-enter="beforeEnter"
    @enter="enter"
    @after-enter="afterEnter"
    @before-leave="beforeLeave"
    @leave="leave"
    @after-leave="afterLeave"
>
    <p v-show="show"></p>
</transition>
methods:{
    beforeEnter(el){
        console.log('动画enter之前');
    },
    enter(el){
        console.log('动画enter进入');
    },
    afterEnter(el){
        console.log('动画进入之后');
    },
    beforeLeave(el){
        console.log('动画leave之前');
    },
    leave(el){
        console.log('动画leave');
    },
    afterLeave(el){
        console.log('动画leave之后');
    }
}

四、transition-group

 <transition> 是一个抽象组件,且只对单个元素生效。而 <transition-group> 组件实现了列表的过渡,并且它会渲染一个真实的DOM元素节点,默认渲染 <span>,可以通过 tag 属性配置哪个元素应该被渲染。 注意,每个 <transition-group> 的子节点必须有独立的 key,动画才能正常工作

【1】用法

<transition-group tag="ul" name="slide">
  <li v-for="item in items" :key="item.id">
    {{ item.text }}
  </li>
</transition-group>

【2】transition-group属性

 tag: string,默认为 span

move-class: 覆盖移动过渡期间应用的 CSS 类。

除了 mode,其他 attribute 和 <transition> 相同

【3】transition-group事件

事件和 <transition> 相同

五、实例

【1】transiton展开收起侧边栏

<template>
    <button @click="show = !show">{{txt}}</button>
    <transition name="fade">
        <div class="leftNav" v-show="show">左侧边栏</div>
    </transition>
</template>

<script>
    export default {
        data() {
            return {
                show: true,
            }
        },
        computed: {
            txt() {
                return this.show ? '收起' : '展开'
            }
        },
    }
</script>

<style>
    .leftNav {
        height: 90vh;
        width: 200px;
        background-color: #ccc;
    }

    /*设置动画*/
    .fade-enter,
    .fade-leave-to {
        transform: translateX(-100%);
    }

    .fade-enter-active,
    .fade-leave-active {
        transition: 1s;
    }

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

 

【2】transiton-map实现多元素收缩展开

<template>
    <button @click="show = !show">{{txt}}</button>
    <transition-group name="move">
        <div class="box" v-show="show" key="1">1</div>
        <div class="box" v-show="show" key="2">2</div>
        <div class="box" v-show="show" key="3">3</div>
        <div class="box" v-show="show" key="4">4</div>
    </transition-group>
</template>

<script>
    export default {
        data() {
            return {
                show: true,
            }
        },
        computed: {
            txt() {
                return this.show ? '收起' : '展开'
            }
        },
    }
</script>

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

    .move-enter-active,
    .move-leave-active {
        transition: 1s;
    }

    .move-enter-to {
        transform: translateX(0)
    }

    .box {
        width: 200px;
        height: 100px;
        background: #ccc;
        margin-bottom: 2px;
    }
</style>

 【3】transiton配合animation动画使用

<template>
    <div>
        <button @click="play('topToTop')">从顶部滑入、顶部滑出</button>
        <button @click="play('topToBottom')">从顶部滑入、底部滑出</button>
        <button @click="play('bottomToTop')">从底部滑入、顶部滑出</button>
        <button @click="play('bottomToBottom')">从底部滑入、底部滑出</button>
        <button @click="play('leftToRight')">从左侧滑入、右侧滑出</button>
        <button @click="play('leftToLeft')">从左侧滑入、左侧滑出</button>
        <button @click="play('rightToLeft')">从右侧滑入、左侧滑出</button>
        <button @click="play('rightToRight')">从右侧滑入、左侧滑出</button>
        <div class="view">
            <transition :name="transName">
                <div v-show="show" class="block">Element</div>
            </transition>
        </div>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                transName: '',
                show: true,
            }
        },
        methods: {
            play(name) {
                this.transName = name;
                this.show = !this.show;
            }
        }
    }
</script>
<style>
    .view {
        position: relative;
        height: 300px;
        width: 300px;
        background: gainsboro;
        overflow: hidden;
    }

    .block {
        position: absolute;
        height: 100%;
        width: 100%;
        text-align: center;
        color: white;
        line-height: 300px;
        background: red;
    }

    /*滑入——从顶部*/
    @keyframes slideIn_top {
        0% {
            top: -100%;
        }

        100% {
            top: 0;
        }
    }

    /*滑入——从底部*/
    @keyframes slideIn_bottom {
        0% {
            top: 100%;
        }

        100% {
            top: 0;
        }
    }

    /*滑入——从左侧*/
    @keyframes slideIn_left {
        0% {
            left: -100%;
        }

        100% {
            left: 0;
        }
    }

    /*滑入——从右侧*/
    @keyframes slideIn_right {
        0% {
            left: 100%;
        }

        100% {
            left: 0;
        }
    }

    /*滑出——从顶部*/
    @keyframes slideOut_top {
        0% {
            top: 0;
        }

        100% {
            top: -100%
        }
    }

    /*滑出——从底部*/
    @keyframes slideOut_bottom {
        0% {
            top: 0;
        }

        100% {
            top: 100%
        }
    }

    /*滑出——从左侧*/
    @keyframes slideOut_left {
        0% {
            left: 0;
        }

        100% {
            left: -100%
        }
    }

    /*滑出——从右侧*/
    @keyframes slideOut_right {
        0% {
            left: 0;
        }

        100% {
            left: 100%
        }
    }

    
    /*(滑入)——从顶部滑入,从顶部滑出*/
    .topToTop-enter-active {
        animation: slideIn_top 1s;
    }
    /*(滑出)——从顶部滑入,从顶部滑出*/
    .topToTop-leave-active {
        animation: slideOut_top 1s;
    }


    /*(滑入)——从顶部滑入,从底部滑出*/
    .topToBottom-enter-active {
        animation: slideIn_top 1s;
    }
    /*(滑出)——从顶部滑入,从底部滑出*/
    .topToBottom-leave-active {
        animation: slideOut_bottom 1s;
    }


    /*(滑入)——从底部滑入,从顶部滑出*/
    .bottomToTop-enter-active {
        animation: slideIn_bottom 1s;
    }
    /*(滑出)——从底部滑入,从顶部滑出*/
    .bottomToTop-leave-active {
        animation: slideOut_top 1s;
    }


    /*(滑入)——从底部滑入,从底部滑出*/
    .bottomToBottom-enter-active {
        animation: slideIn_bottom 1s;
    }
    /*(滑出)——从底部滑入,从底部滑出*/
    .bottomToBottom-leave-active {
        animation: slideOut_bottom 1s;
    }


    /*(滑入)——从左侧滑入,从右侧滑出*/
    .leftToRight-enter-active {
        animation: slideIn_left 1s;
    }
    /*(滑出)——从左侧滑入,从右侧滑出*/
    .leftToRight-leave-active {
        animation: slideOut_right 1s;
    }


    /*(滑入)——从左侧滑入,从左侧滑出*/
    .leftToLeft-enter-active {
        animation: slideIn_left 1s;
    }
    /*(滑出)——从左侧滑入,从左侧滑出*/
    .leftToLeft-leave-active {
        animation: slideOut_left 1s;
    }


    /*(滑入)——从右侧滑入,从左侧滑出*/
    .rightToLeft-enter-active {
        animation: slideIn_right 1s;
    }
    /*(滑出)——从右侧滑入,从左侧滑出*/
    .rightToLeft-leave-active {
        animation: slideOut_left 1s;
    }


    /*(滑入)——从右侧滑入,从右侧滑出*/
    .rightToRight-enter-active {
        animation: slideIn_right 1s;
    }
    /*(滑出)——从右侧滑入,从右侧滑出*/
    .rightToRight-leave-active {
        animation: slideOut_right 1s;
    }
</style>

 

 文章每周持续更新,可以微信搜索「 前端大集锦 」第一时间阅读,回复【视频】【书籍】领取200G视频资料和30本PDF书籍资料

### 回答1: Vuetransition过渡动画Vue.js框架中用来实现组件的进入和离开过渡效果的功能。它可以在组件的挂载和卸载时自动添加/删除 CSS 类名,实现过渡效果。开发者可以通过添加自定义的 CSS 类名来实现不同的过渡效果。 ### 回答2: Vuetransition过渡动画是一种在元素进入或离开DOM时自动添加动画效果的机制。它基于CSS3的transition和animation属性来实现,并且Vue提供了一些API用于手动控制过渡动画的行为。在Vue中,可以通过以下几个步骤来实现过渡动画的效果: 1. 定义CSS过渡效果:使用CSS transition或animation属性定义元素的进入和离开动画,同时使用Vue提供的CSS类名来指定不同状态下的样式,例如v-enter、v-leave-to等。 2. 在组件中添加<transition>标签:将需要添加过渡动画的元素包裹在<transition>标签中,同时添加name属性指定该过渡动画的名称,并使用CSS类名来指定不同状态下的样式。 3. 使用Vue提供的过渡钩子函数:在组件的变化过程中,Vue提供了一系列的过渡钩子函数,如before-enter、enter、leave等,在这些函数中可以手动控制过渡动画的行为,例如添加自定义类名、动态修改CSS属性等。 通过以上步骤,我们就可以在Vue实现任意复杂的过渡动画效果,例如淡入淡出、旋转、缩放等等。同时,Vue过渡动画还支持多个元素同时进行动画、并行和串行动画等高级特性,可以满足多样化的动画需求。总之,Vuetransition过渡动画是一种非常强大、易用且高度可定制的动画机制,在前端开发中有着广泛的应用。 ### 回答3: Vuetransition过渡动画是一个常用的页面交互效果,在Vue中使用transition可以实现从一个状态到另一个状态的平滑过渡效果。 如何使用Vue transition: 1. 定义过渡样式 在 Vue 中使用transition需要自定义过渡样式。Vue过渡是以类名的形式加在元素上,所以需要定义好过渡的类名和CSS样式,如下: ``` .Fade-enter-active, .Fade-leave-active { transition: opacity .5s; } .Fade-enter, .Fade-leave-to { opacity: 0; } ``` 上面这个例子中,`.Fade-enter-active`和`.Fade-leave-active`是Vue过渡动画默认的类名,分别表示进入和离开状态时的动画。 2. 定义过渡组件 定义好过渡样式后,就需要在 Vue 组件中使用过渡,如下: ``` <transition name="Fade"> <div v-if="show">这是一个过渡动画</div> </transition> ``` `<transition>`标签内部是需要过渡的内容,`name`属性表示定义的过渡样式的名称。 3. 触发过渡效果 在Vue组件中使用 `v-if` 或 `v-show` 指令来控制元素的显示和隐藏,就可以触发过渡效果。 例如: ``` <script> export default { data () { return { show: true } }, methods: { toggleShow () { this.show = !this.show } } } </script> <template> <button @click="toggleShow">toggleShow</button> <transition name="Fade"> <div v-if="show">这是一个过渡动画</div> </transition> </template> ``` 在这个例子中,点击按钮时,`show`属性的值会发生变化,从而触发过渡效果。 总结: 使用Vue transition可以让页面在元素状态发生变化时产生平滑的过渡效果,提升页面交互的体验。在使用时需要定义好过渡样式和过渡组件,并在Vue组件中使用`v-if`或`v-show`指令控制元素的显示和隐藏,从而达到触发过渡效果的目的。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

@Demi

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

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

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

打赏作者

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

抵扣说明:

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

余额充值