Vue中的動畫效果


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

  1. 在 CSS 過渡和動畫中自動應用 class
  2. 可以配合使用第三方 CSS 動畫庫,如 Animate.css
  3. 在過渡鈎子函數中使用 JavaScript 直接操作 DOM
  4. 可以配合使用第三方 JavaScript 動畫庫,如 Velocity.js

下面分別從這個4個工具來學習Vue動畫效果。

一、單元素/組件的過渡

Vue 提供了 transition 的封裝組件,在下列情形中,可以給任何元素和組件添加進入/離開過渡

  • 條件渲染 (使用 v-if)
  • 條件展示 (使用 v-show)
  • 動態組件
  • 組件根節點

一個典型的例子:

Html文件

<div id="app">
        <transition name="fade">
            <div v-if="show">
                Hello world.
            </div>
        </transition>
        <button @click="handleClick">切換</button>
    </div>

  

js文件

<script>

        // 1. 創建Vue的實例
        let vm = new Vue({
            el:'#app',
            data:{
                show:false
            },
            methods:{
                handleClick:function(){
                    this.show = !this.show
                }
            }
        });
    </script>

  

css文件

<style>
        .fade-enter-active, .fade-leave-active {
          transition: opacity 2s;
        }
        .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
          opacity: 0;
        }
</style>

  

這個例子的效果為:點擊切換,文字會淡入淡出。

實現原理:

1、通過使用transition組件后, Vue 將會做以下處理:

  • 自動嗅探目標元素是否應用了 CSS 過渡或動畫,如果是,在恰當的時機添加/刪除 CSS 類名。
  • 如果過渡組件提供了 JavaScript 鈎子函數,這些鈎子函數將在恰當的時機被調用。
  • 如果沒有找到 JavaScript 鈎子並且也沒有檢測到 CSS 過渡/動畫,DOM 操作 (插入/刪除) 在下一幀中立即執行。(注意:此指瀏覽器逐幀動畫機制,和 Vue 的 nextTick 概念不同)

2、動畫進入時,Vue會添加CSS類,如果沒有使用name="fade"的話,類名為v-fade-enter、v-fade-eneter-active等。

第一幀動畫,會自動添加fade-enter和fade-enter-active類

第二幀動畫,會去掉fade-enter類,添加fade-enter-to類

第三幀動畫,會去掉所有enter類

 

 3、動畫在離開時同樣會添加或刪除CSS類

 

二、Vue使用animate.css動畫庫

1、使用自定義類

效果為:進入或離開都會有拉升效果。

注意:這里我們使用了

name="bounce"替換了默認的fade。當然,如果沒有fade的話,也會有v-作為默認開頭。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        
        @keyframes bounce-in {
          0% {
            transform: scale(0);
          }
          50% {
            transform: scale(1.5);
          }
          100% {
            transform: scale(1);
          }
        }


        .bounce-enter-active {
          animation: bounce-in .5s;
        }
        .bounce-leave-active {
          animation: bounce-in .5s reverse;
        }
</style>

</head>
<body>
    <div id="app">
        <transition name="bounce">
            <div 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.
            </div>
        </transition>
        <button @click="handleClick">切換</button>
    </div>

    <script src="js/vue.js"></script>
    <script>

        // 1. 創建Vue的實例
        let vm = new Vue({
            el:'#app',
            data:{
                show:false
            },
            methods:{
                handleClick:function(){
                    this.show = !this.show
                }
            }
        });
    </script>
    </body>
    </html>

  我們這里還可以使用自定義類:

 

 既然我們可以使用自定義class,那么我們就可以使用開源的第三方CSS庫,比如animate.css庫。

https://daneden.github.io/animate.css/

使用很簡單,直接替換上面我們自定義的class就行。

使用animate.css注意事項:

1、必須使用自定義class的模式

enter-active-class=""

2、animated類放在前面,且是必須的

 

三、Vue中同時使用過渡和動畫

1、初次動畫效果

上面例子中,我們初次進入的時候沒有動畫效果,我們可以做如下修改:

 

 2、如果我們希望在上面的例子中還加入一開始我們說的過渡效果,那該怎么做呢?

 1、因為animate.css有一個自己的動畫效果時長,fade也有一個opacity,那么以哪一個為准呢?我們可以使用type="transition"來確定哪個為准。

2、我們也可以自己設定動畫效果時長樣式:duration里面的enter為進入時長,leave為動畫離開時長,都是針對過渡效果的。

 

四、Vue中的js動畫配合使用第三方動畫庫(Velocity.js) 

 Html

<div id="app">
        <transition name="fade"
        @before-enter="beforeEnter"
        @enter="enter"
        >
            <div 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.
            </div>
        </transition>
        <button @click="handleClick">切換</button>
    </div>

  

Js

 methods:{
                handleClick:function(){
                    this.show = !this.show
                },
                beforeEnter: function (el) {
                  el.style.opacity = 0
                  el.style.transformOrigin = 'left'
                },
                enter: function (el, done) {
                  Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 })
                  Velocity(el, { fontSize: '1em' }, { complete: done })
                },
            }

  

五、多個元素或組件的過渡動畫

1、多個元素的過渡動畫實現

Html

 <div id="app">
        <transition name="fade" mode="in-out">
            <div v-if="show" key='one'>組件1</div>
            <div v-else key='two'>組件2</div>
        </transition>
        <button @click="handleClick">切換</button>
    </div>

  

style

<style>
        .fade-enter-active, .fade-leave-active {
          transition: opacity 1s;
        }
        .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
          opacity: 0;
        }
</style>

  注意:這里需要綁定一個key,因為vue會復用,所以不加key就不會有效果。

 

2、多個組件的過渡動畫實現

Html

<div id="app">
        <transition name="fade" >
           <child-one v-if="show"></child-one>
           <child-two v-else></child-two>
        </transition>
        <button @click="handleClick">切換</button>
    </div>

  

js

<script>
        Vue.component('child-one',{
            template:'<div>child-one</div>'
        })
        Vue.component('child-two',{
            template:'<div>child-two</div>'
        })
        // 1. 創建Vue的實例
        let vm = new Vue({
            el:'#app',
            data:{
                show:false
            },
            methods:{
                handleClick:function(){
                    this.show = !this.show
                }
            }
        });
    </script>

  

css

<style>
        .fade-enter-active, .fade-leave-active {
          transition: opacity .4s;
        }
        .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
          opacity: 0;
        }
</style>

  

我們可以通過Vue自帶的compoent標簽實現動態組件,data中show改成type,type:‘child-one’

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .fade-enter-active, .fade-leave-active {
          transition: opacity .4s;
        }
        .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
          opacity: 0;
        }
</style>

</head>
<body>
    <div id="app">
        <transition name="fade" >
            <component :is="type"></component>
          
        </transition>
        <button @click="handleClick">切換</button>
    </div>

    <script src="js/vue.js"></script>
    <script>
        Vue.component('child-one',{
            template:'<div>child-one</div>'
        })
        Vue.component('child-two',{
            template:'<div>child-two</div>'
        })
        // 1. 創建Vue的實例
        let vm = new Vue({
            el:'#app',
            data:{
                type:'child-one'
            },
            methods:{
                handleClick:function(){
                    this.type = this.type==='child-one'?'child-two':'child-one'
                }
            }
        });
    </script>
    </body>
    </html>

  

六、Vue中列表的過渡動畫

 當我們希望對列表進行過渡效果時,使用transition-group標簽就可以了。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .fade-enter-active, .fade-leave-active {
          transition: opacity 1s;
          color: red;
        }
        .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
          opacity: 0;
        }
</style>

</head>
<body>
    <div id="app">
        <transition-group name="fade">
            <div v-for="item in list" key="item.id">{{item.title}}</div>
        </transition-group>
        
        <button @click="handleClick">增加</button>
    </div>

    <script src="js/vue.js"></script>
    <script>
        var count = 0
        // 1. 創建Vue的實例
        let vm = new Vue({
            el:'#app',
            data:{
               list:[]
            },
            methods:{
                handleClick:function(){
                    this.list.push({
                        id:count++,
                        title:'hello kitty!'

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

  

七、動畫封裝

我們可以將動畫以組件的方式進行封裝起來,以后需要使用這個動畫時,直接通過插槽將組件放入插槽即可。

例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src='js/velocity.min.js'></script>

</head>
<body>
    <div id="app">
       <fade :show="show">
           <div>
               hello div
           </div>
       </fade>
       <fade :show="show">
           <h1>hello H1</h1>
       </fade>
        
        <button @click="handleClick">增加</button>
    </div>

    <script src="js/vue.js"></script>
    <script>
        Vue.component('fade',{
            props:['show'],
            template:`<transition @before-enter="handleBeforeEnter"
            @enter="handleEnter">
             <slot v-if="show"></slot>
            </transition>`,
            methods:{
                handleBeforeEnter:function(el){
                    el.style.color="red"
                },
                handleEnter:function(el,done){
                    setTimeout(()=>{
                        Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 })
                        Velocity(el, { fontSize: '1em' }, { complete: done })
                        done()
                    },2000)
                }
            }
        })
        // 1. 創建Vue的實例
        let vm = new Vue({
            el:'#app',
            data:{
               show:false
            },
            methods:{
                handleClick:function(){
                    this.show=!this.show
                }
            }
        });
    </script>
    </body>
    </html>

  我們這里封裝了一個fade組件,通過transition封裝一個slot,里面可以支持N個內容。然后將動畫效果封裝到鈎子函數,然后在鈎子函數里面放入CSS效果。這樣,就將動畫效果完全封裝在一個組件中了,隨時隨地可以使用這個帶動畫的組件啦。

寫了這么多,其實就是開頭的四種方式:

  1. 在CSS過渡和動畫中自動應用class【默認為fade開頭,也可以自定義,不寫name時為v開頭】
  2. 可以配合使用第三方 CSS 動畫庫,如 Animate.css【自定義class的方式】
  3. 在過渡鈎子函數中使用 JavaScript 直接操作 DOM
  4. 可以配合使用第三方 JavaScript 動畫庫,如 Velocity.js

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM