Vue2过渡&动画

本文详细介绍了Vue2中的过渡效果,包括单元素/组件的过渡、过渡的类名变化、多个组件的过渡、列表过渡及其进入/离开过渡,以及如何创建可复用的过渡组件。内容涵盖CSS和JavaScript钩子的使用,以及过渡模式的设置,帮助开发者更好地理解和应用Vue2的过渡动画效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.单元素/组件的过渡

2.过渡的类名

初始渲染的过渡

多个元素的过渡

过渡模式

3.多个组件的过渡

4.列表过渡

列表的进入/离开过渡

5.可复用的过渡


1.单元素/组件的过渡

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

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

简单案例

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

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

  1. 自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名。
  2. 如果过渡组件提供了JavaScript钩子函数,这些钩子函数将在恰当的时机被调用。
  3. 如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作 (插入/删除) 在下一帧中立即执行。

2.过渡的类名

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

  1. v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
  2. v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
  3. v-enter-to:2.1.8 版及以上定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。
  4. v-leave:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
  5. v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
  6. v-leave-to:2.1.8 版及以上定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。

 

初始渲染的过渡

可以通过 appear attribute 设置节点在初始渲染的过渡

<transition appear>
  <!-- ... -->
</transition>

 这里默认和进入/离开过渡一样,同样也可以自定义 CSS 类名。

<transition
  appear
  appear-class="custom-appear-class"
  appear-to-class="custom-appear-to-class"
  appear-active-class="custom-appear-active-class"
>
  <!-- ... -->
</transition>

多个元素的过渡

我们之后讨论多个组件的过渡,对于原生标签可以使用 v-if/v-else。最常见的多标签过渡是一个列表和描述这个列表为空消息的元素:

<transition>
  <div v-if="items.length > 0">
    <!-- ... -->
  </div>
  <p v-else>Sorry, no items found.</p>
</transition>

可以这样使用,但是有一点需要注意:

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

如下:

<transition>
  <button v-if="isEditing" key="save">
    Save
  </button>
  <button v-else key="edit">
    Edit
  </button>
</transition>

过渡模式

同时生效的进入和离开的过渡不能满足所有要求,所以 Vue 提供了过渡模式

  • in-out:新元素先进行过渡,完成之后当前元素过渡离开。
  • out-in:当前元素先进行过渡,完成之后新元素过渡进入。

如果没有这个过渡模式,传统实现方案,采用定位也可以解决。

只用添加一个简单的 attribute,就解决了之前的过渡问题而无需任何额外的代码。

<transition name="fade" mode="out-in">
  <!-- ... the buttons ... -->
</transition>

3.多个组件的过渡

多个组件的过渡简单很多 - 我们不需要使用 key attribute。相反,我们只需要使用动态组件:

<transition name="component-fade" mode="out-in">
  <component v-bind:is="view"></component>
</transition>

4.列表过渡

目前为止,关于过渡我们已经讲到:

  • 单个节点
  • 同一时间渲染多个节点中的一个

那么怎么同时渲染整个列表,比如使用 v-for?在这种场景中,使用 <transition-group> 组件。

在我们深入例子之前,先了解关于这个组件的几个特点:

  • 不同于 <transition>,它会以一个真实元素呈现:默认为一个 <span>。你也可以通过 tag attribute 更换为其他元素。
  • 过渡模式mode属性不可用,因为我们不再相互切换特有的元素。
  • 内部元素总是需要提供唯一的 key attribute 值,并且避免使用index索引
  • CSS 过渡的类将会应用在内部的元素中,而不是这个组/容器本身。 ul 和li,动画产生在li,不会在ul上产生动画

列表的进入/离开过渡

现在让我们由一个简单的例子深入,进入和离开的过渡使用之前一样的 CSS 类名。

<div id="list-demo" class="demo">
  <button v-on:click="add">Add</button>
  <button v-on:click="remove">Remove</button>
  <transition-group name="list" tag="p">
    <span v-for="item in items" v-bind:key="item" class="list-item">
      {{ item }}
    </span>
  </transition-group>
</div>
new Vue({
  el: '#list-demo',
  data: {
    items: [1,2,3,4,5,6,7,8,9],
    nextNum: 10
  },
  methods: {
    randomIndex: function () {
      return Math.floor(Math.random() * this.items.length)
    },
    add: function () {
      this.items.splice(this.randomIndex(), 0, this.nextNum++)
    },
    remove: function () {
      this.items.splice(this.randomIndex(), 1)
    },
  }
})

5.可复用的过渡

过渡可以通过 Vue 的组件系统实现复用。要创建一个可复用过渡组件,你需要做的就是将 <transition> 或者 <transition-group> 作为根组件,然后将任何子组件放置在其中就可以了。

使用 template 的简单例子:

Vue.component('my-special-transition', {
  template: '\
    <transition\
      name="very-special-transition"\
      mode="out-in"\
    >\
      <slot></slot>\
    </transition>\
  ',
  methods: {
    
  }
})

抽屉案例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
    <title>Document</title>
    <script src="./vue.js"></script>
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
      />
    <style>
      *{margin:0;padding:0;}
      body,html{
      height:100%;

      }

      .fade-enter-active{
      animation: aa 1s;
      }

      .fade-leave-active{
      animation: aa 1s reverse;
      }

      @keyframes aa{
      0%{
      opacity:0;
      }

      100%{
      opacity:1;
      }
      }

      .left{
      position:fixed;
      top:0;
      left:0;
      background-color:red;
      }

      .left-enter-active{
      animation: leftframe 1s;
      }

      .left-leave-active{
      animation: leftframe 1s reverse;
      }


      @keyframes leftframe {
      0%{
      /* opacity:0; */
      transform: translateX(-100%);
      }

      100%{
      /* opacity:1; */
      transform: translateX(0px);
      }
      }



      .right{
      position:fixed;
      top:0;
      right:0;
      background-color:red;
      }

      .right-enter-active{
      animation: rightframe .3s;
      }

      .right-leave-active{
      animation: rightframe .3s reverse;
      }


      @keyframes rightframe {
      0%{
      /* opacity:0; */
      transform: translateX(100%);
      }

      100%{
      /* opacity:1; */
      transform: translateX(0px);
      }
      }



    </style>
  </head>
  <body>
    <!-- https://animate.style/ -->
    <!-- animate__animated 第一个:必须要有的 不要动-->
    <!-- animate__bounce  第二个:代表执行哪个动画-->

    <!-- <h1 class="animate__animated animate__bounceOutLeft">An animated element</h1> -->


    <div id="app">

      <button @click="isShow = !isShow">切换</button>

      <transition name="fade">
        <div v-if="isShow">内容1------</div>
        </transition>

        <div>---------------------------</div>

        <fade>
        <div v-if="isShow">内容2------</div>
        </fade>

        <!-- 组件完成模块或功能的封装,实现可复用 -->
        <!-- 插槽在组件的基础上完成内容的分发 -->

        <div>----------------------------</div>
        <div>
        <button @click="show('left')">left显示</button>
        <button @click="hide()">隐藏</button>
        </div>

        <div>
        <button @click="show('right')">right显示</button>
        <button @click="hide()">隐藏</button>
        </div>

        <!-- v-if v-show -->
        <drawer :placement="pos" :show="sliderShow"></drawer>
        </div>

        <script>

        Vue.component('fade',{
        template:`
        <transition name="fade">
        <slot></slot>
        </transition>
        `
        });


        Vue.component('drawer',{
        props:{
        title:{
        default:'标题'
        },
        placement:{
        default:'left'
        },
        show:{
        default:false
        }
        },
        template:`
        <transition :name="placement">
        <div :class="placement" v-if="show">
        <h5 v-text="title"></h5>
        <div>
        content
        </div>
        </div>
        </transition>
        `
        });

        var vm = new Vue({
        el:'#app',
        data:{
        isShow:true,
        sliderShow:false,
        pos:'left'
        },
        methods:{
        show(pos){
        this.pos = pos;
        this.sliderShow = true;
        },
        hide(){
        this.sliderShow = false;
        }
        }
        });

        </script>

        </body>
        </html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值