vue 动画原理

131 阅读5分钟

方法:CRM

C:内容来源

进入/离开 & 列表过渡 — Vue.js (vuejs.org)

R: 学习目录

  • ①transition 过渡

  • ②animation 动画

  • ③钩子+ velocity.js + done()

  • ④button key='xxx' + mode=out-in/in-out

  • ⑤ xxx=v-a/v-b

  • ⑥列表动画

M:

一、transition 过渡

1. Copy :

进入/离开 & 列表过渡 — Vue.js (vuejs.org)

2. Run :

首先去掉transition标签和css中的内容,写出button和条件展示,button更改条件变量,p中写条件v-if

    <head>
        <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.4/vue.js"></script>
          <!--引入vue-->
    <head>
    <body>
        <div id = 'example-1'>
            <button @click="show=!show">Toggle</button>
            <p v-if="show">halo~</p>
        </div>
    </body>

js中如果不确定vue是否被成功引入,可以console.log(window.Vue),然后打开控制台查看

        new Vue({
            el : '#example-1',
            data : {show : true},
        })

这是不加动画效果的原本的代码,加动画效果,则是在目标元素上加上transition标签,然后name给css标识,通过name,css再通过过渡的类名,实现过渡效果。

        <transition name="fade"> 
            <p v-if="show">hello</p> 
        </transition>

在css中写过渡效果

        .fade-enter-active, .fade-leave-active { 
        transition: opacity .5s;
        } ;
        .fade-enter, .fade-leave-to {
        opacity: 0; 
        }

3.Modify

要修改元素进行transition的过渡,就要知道这段代码的关键点在哪。

  • 首先,过渡只是一种效果,展示变化,给变化延长了时间和丰富了样式。因此,要先把加过渡前的代码写好,明确哪里需要加过渡样式。

  • 其次,写transition样式,在html中transition作为标签,包裹住变化的范围,然后name给css标识。

  • 最后,在css中写变化的样式。修改这一部分的时候,需要前置一些铺垫知识。了解过渡的类名:进入/离开 & 列表过渡 — Vue.js (vuejs.org)。和这些类名里面一般写什么(这些看例子可以理解)。

二、 animation 动画

graph TD
transition过渡 --> css过渡 --> css动画 --> animotion
  • 先对animation 动画进行一下铺垫,css过渡,css过渡和transition过渡相比,多的是用css的语法来写过渡效果。 例如:
        .fade-enter-active, .fade-leave-active { 
        transition: opacity .5s;
        } ;
        .fade-enter, .fade-leave-to {
        opacity: 0; 
        transform : translateX(20px)
        }
  • 从css过渡到css动画。就是过渡和动画的区别,过渡的帧数固定,而动画可以定义有多少帧,并进行设置。
  • 从css动画到animotion。CSS 动画用法同 CSS 过渡,区别是在动画中 v-enter 类名在节点插入 DOM 后不会立即删除,而是在 animationend 事件触发时删除。具体来讲animationend就是,原先案例中的css的过渡类名中写的transition改成animation。

Copy :

进入/离开 & 列表过渡 — Vue.js (vuejs.org)

Run :

<head>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.4/vue.min.js"></script>
</head>
<body>
    <div id='example-2'>
        <button @click='show=!show'>Toggle</button>
        <transition @name='fade'>
        <p v-if="show">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris facilisis enim libero, at lacinia diam fermentum id. Pellentesque habitant morbi tristique senectus et netus.</p>
       </transition>
    </div>
</body>

写在js中

  new Vue({
     el:'#example-2',
     data : {
        show = true
     }
  })

css中写动画样式

        .fade-enter-active{
            animation : fade-in 1s;
        }
        .fade-leave-active{
            animation : fade-in 1s reverse
        }
        @keyframes fade-in{
            0%{
                transform : scale(0)
            }
            50%{
                transform : scale(1.5)
            }
            100%{
                transform : scale(1)
            }
        
        }

Modify :

大部分和写transition过渡的时候没有差别,唯一的差别就在写动画样式的时候,transition中使用的是过渡类名中写transition,而这里写的是animation + 自定义动画名(fade-in),而后使用@keyframes + 自定义动画名来写动画。

三、钩子

在这里的js钩子,配合done()和velocity.js使用

在Vue中钩子的意思即为生命周期的节点,动画中钩子的意思就是动画生命周期中的节点。

Copy:

进入/离开 & 列表过渡 — Vue.js (vuejs.org)

Run:

<head>
  <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.7.4/vue.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
</head>
<body>
    <div id='example-3'>
        <button @click='show = !show'>Toggle</button>
        <transition
         @before-enter = 'beforeEnter'           
         @enter = 'enter' 
         @leave = 'leave' 
         :css = 'false'>
            <p v-if='show'>Demmo</p>
        </transition>
    </div>    
</body>       

因为引用velocity,所以css样式写在js中

   new Vue({
      el : '#example-3',
      data : {
          show : true
      },
      
      methods:{
         beforeEnter(el){
            el.style.opacity =0 
            el.style.transformOrigin = 'left'
        },
        enter(el,done){
            Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 })
            Velocity(el, { fontSize: '1em' }, { complete: done })
        }
        leave(el,done){
            Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 })
            Velocity(el, { rotateZ: '100deg' }, { loop: 2 })
            Velocity(el, {
                rotateZ: '45deg',
                translateY: '30px',
                translateX: '30px',
                opacity: 0}, { complete: done })
        }
      }
        
   })

Modify:

  • 在html中引入velocity,在transition标签中写好钩子,@before-enter/v-on:before-enter = 'before',然后在js的methods中写函数,决定过渡或者动画的样式。

  • enter和leave钩子必须要done()函数进行回调,否则他们会被同步调用,过渡立即完成。

  • v-bind:css="false",Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。

  • velocity的使用自己看看就好了。

四、多个元素的过渡

Copy:

进入/离开 & 列表过渡 — Vue.js (vuejs.org)

Run:

   <div id='example-4'>
       <transition name='fade' mode='in-out'>
           <button v-if='status==="off"' @click='status="on"' key='on'>on</button>
           <button v-if='status==="on"' @click='status="off"' key='off'>off</button>
       </transition>
   </div>

然后写js

   new Vue({
        el:'#example-4',
        data:{
            status:'on'
        }
   })

写css

   .fade-enter-active,.fade-leave-active{
        transition: 1s all
   }
   .fade-enter{
        transform : translateX(20px)
        opacity : 0
   }
   .fade-leave-to{
        transform : translateX(-20px)
        background : pink
   }
   #example-4{
        position : relative
   }
   button{
        position : absolute
   }
        
        

Modify:

  • mode是过渡模式,in-out:新元素先进,旧元素再出去;out-in则相反旧出再新进。 * key attribute 设置不同的状态来代替 v-if 和 v-else

五、多个组件的过渡

元素用key来进行选择,组件就用components。

Copy:

进入/离开 & 列表过渡 — Vue.js (vuejs.org)

Run:

  <div id="example-5">
      <input type="radio" id="a" value="A" v-model="picked" @click='show="v-a"'>
      <label for="a">A</label>
      <br>
      <input type="radio" id="b" value="B" v-model="picked" @click='show="v-b"'>
      <label for="b">B</label>
      <br>
   
      <transition name='fade'>
        <component :is='show'></component>
      </transition>
</div>  

写js

   new Vue({
       el : '#example-5',
       data : {
        picked : '',
        show : 'v-a'
       },
       components : {
        'v-a' : {
            template : `<div>Component A</div>`
        },
        'v-b' : {
            template : `<div>Component B</div>`
        }
       }
   })

最后就是css

   .fade-enter-active, .fade-leave-active { 
        transition: opacity .3s ease; 
    } 
   .fade-enter, .fade-leave-to{ 
        opacity: 0; 
    }     

Modify:

  • component和components

六、列表过渡

前面都是单元素或者多元素组件的过渡,这里将列表过渡

Copy:

进入/离开 & 列表过渡 — Vue.js (vuejs.org)

Run:

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

然后写js

      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) 
            }, 
        } 
       })

最后补充css

        .list-item { 
            display: inline-block; margin-right: 10px; 
        } 
        .list-enter-active, .list-leave-active {
            transition: all 1s; 
        } 
        .list-enter, .list-leave-to {
            opacity: 0; transform: translateY(30px); 
        }

Modify:

  • transition-group tag='p'

  • v-for :key

last

详细了解过程,可以通过查看,控制台的element中dom元素的变化来观察。