Vue3 | 動畫專題 完整原文地址見簡書https://www.jianshu.com/p/f3b52299aaa6 本文內容提要

完整原文地址見簡書https://www.jianshu.com/p/f3b52299aaa6



本文內容提要

  • Vue常規動畫寫法

  • Vue過渡動畫 常規寫法與 例程

  • 上例的另一種實現方式

  • 入場動畫

  • 出場動畫

  • 出入場動畫同時實現時,可以簡化以上代碼

  • 出場入場幀動畫

  • 使用name=對動畫進行 片段式地 命名

  • 對動畫類的完全命名

  • 完全命名的方式 使得 容易接入 第三方庫

  • 注意以上案例,將v-if換成v-show也是可以正常運行的

  • 顏色過渡和位移 動畫 結合

  • 控制組合動畫時長 以某一類型動畫的時間爲準

  • 控制組合動畫時長 以自定義的時長爲準

  • 分別 統一 出入場動畫的時延

  • 禁用CSS動畫,使用JS動畫

  • 最基本的 多個 單元素標籤 切換案例

  • 帶上入場 退場 動畫的 兩個單元素標籤切換

  • 帶上入場 退場 動畫的 兩個組件 的切換

  • <component>組件佔位 + is屬性 + 雙向綁定特性 實現上例效果

  • 列表動畫

  • 狀態動畫


Vue常規動畫寫法

關鍵幀 --- CSS類 --- data數據 --- DOM的Class屬性

-- 使用@keyframes [關鍵幀實例名]配置好關鍵幀;
-- 使用animation配置關鍵幀以及動畫過程到完成時延
完成動畫的定義【寫在一個CSS類中(如下的myAnimation)】;
-- 在data中定義一個以 上面定義的動畫CSS類實例(如myAnimation) 爲屬性值的 數據字段(如myAnimateData);
-- 在dom中使用:class=[以 動畫CSS類實例 爲屬性的 數據字段]
引用這個數據字段myAnimateData)即可,至此完成動畫定義;
-- 數據字段(如myAnimateData)中,可以通過對 屬性值即動畫CSS類實例的 布爾值的 改變,
去控制動畫的開關,如下 配置false 爲關:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <style>
        @keyframes leftToRight {
            0% {
                transform: translateX(-100px);
            }
            50% {
                transform: translateX(-50px);
            }
            0% {
                transform: translateX(0px);
            }
        }
        .myAnimation {
            animation: leftToRight 3s;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="heheApp"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                myAnimateData: {
                    myAnimation: false
                }
            }
        },
        template: `
            <div>
                <div :class="myAnimateData">heheheda</div>
            </div>`        
    });

    const vm = app.mount('#heheApp');
</script>
</html>

運行效果,沒有動畫,DOM中也沒顯示對應的class:


改爲true:

<script>
    const app = Vue.createApp({
        data() {
            return {
                myAnimateData: {
                    myAnimation: true
                }
            }
        },
        template: `
            <div>
                <div :class="myAnimateData">heheheda</div>
            </div>`        
    });

    const vm = app.mount('#heheApp');
</script>

運行時產生動畫:

可以配合按鈕和點擊事件,動態 交互地 開關動畫:

<script>
    const app = Vue.createApp({
        data() {
            return {
                myAnimateData: {
                    myAnimation: true
                }
            }
        },
        methods: {
          handleClick() {
            this.myAnimateData.myAnimation = !this.myAnimateData.myAnimation;
          }
        },
        template: `
            <div>
                <div :class="myAnimateData">heheheda</div>
                <button @click="handleClick">切換</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>


Vue過渡動畫 常規寫法與 例程

-- 使用transition: [時延] background-color ease;定義 在一個時延內的過渡動畫
background-color指定過渡對象是背景顏色ease指定爲平緩地進行
-- 類似上例,在組件的data中,定義一個 對應CSS類的 Object類型數據字段,並在其中包含過渡動畫定義好的背景顏色的數據字段;
-- 在template中,使用:class=[類實例名]引用data中的CSS類實例即可;
-- 可以準備一個觸發事件,在事件中反轉兩個背景顏色值,由此可實現過渡動畫:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <style>
        .myTransition {
          transition: 3s background-color ease;
        }
        .aquamarine {
          background-color: aquamarine;
        }
        .orange {
          background-color: orange;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="heheApp"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                myTransitData: {
                  myTransition: true,
                  aquamarine: true,
                  orange: false
                }
            }
        },
        methods: {
          handleClick() {
            this.myTransitData.aquamarine = !this.myTransitData.aquamarine;
            this.myTransitData.orange = !this.myTransitData.orange;
          }
        },
        template: `
            <div>
                <div :class="myTransitData">heheheda</div>
                <button @click="handleClick">使用transition切換背景色</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>
</html>

運行效果:

點擊按鈕 觸發事件後 過渡的中途:過渡完畢:


上例的另一種實現方式

-- 定義css動畫類
在dom節點直接使用class=[CSS動畫類]配置上這個CSS動畫類;
-- data中定義初始背景顏色鍵值,打包成object類型,
配置到DOM節點的:style=上,作雙向綁定
-- 把css中定義的背景顏色字段都去掉,
直接寫在觸發事件的方法中,在其中通過更改綁定的style字段的值改變背景顏色;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <style>
        .myTransition {
          transition: 3s background-color ease;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="heheApp"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                styleObj: {
                  background: "aquamarine"
                }
            }
        },
        methods: {
          handleClick() {
            if (this.styleObj.background === 'aquamarine') {
                    this.styleObj.background = 'orange';
                } else {
                    this.styleObj.background = 'aquamarine';
                }
            }
        },
        template: `
            <div>
                <div class="myTransition" :style="styleObj" >heheheda</div>
                <button @click="handleClick">使用transition切換背景色</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>
</html>

運行效果如上例;


入場動畫

如下,
<style>標籤定義的三個類,
分別指定 入場動畫開始時的透明度、
過程持續的時延速度(ease -- 緩慢)、
入場動畫的結束時的透明度;
template中,
使用<transition>標籤對 包裹 要實現入場動畫的DOM節點即可;

<head>
    ...
    <style>
        .v-enter-from{
            opacity: 0;
        }
        .v-enter-active {
            transition: opacity 3s ease;
        }
        .v-enter-to {
            opacity: 1;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="heheApp"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
          handleClick() {
            this.show = !this.show;
          }  
        },
        template: `
            <div>
                <transition>
                    <div v-if="show">heheda</div>
                </transition>
                <button @click="handleClick">切換</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>
</html>

運行效果,實現入場動畫:
初始:

入場中:入場完畢:


出場動畫

理同入場動畫,其中,
v-leave-from表示 出場動畫開始時的透明度、
v-leave-active表示過程持續的時延速度(ease -- 緩慢)、
v-leave-to表示出場動畫的結束時的透明度;
其餘步驟 同入場動畫:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <style>
        .v-enter-from{
            opacity: 0;
        }
        .v-enter-active {
            transition: opacity 3s ease-out;
        }
        .v-enter-to {
            opacity: 1;
        }

        .v-leave-from {
            opacity: 1;
        }
        .v-leave-active {
            transition: opacity 3s ease-in;
        }
        .v-leave-to {
            opacity: 0;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="heheApp"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
          handleClick() {
            this.show = !this.show;
          }  
        },
        template: `
            <div>
                <transition>
                    <div v-if="show">heheda</div>
                </transition>
                <button @click="handleClick">切換</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>
</html>

運行效果:
初始:

切換中:切換結束:


出入場動畫同時實現時,可以簡化以上代碼

兩個v-xxx-active可以寫到一起,
如果v-leave-from指定的值與v-enter-to相同(一般都是相同的),那也可以省略它;
以下代碼實現的效果,同上:

...
        <style>
        .v-enter-from{
            opacity: 0;
        }
        .v-enter-active,
        .v-leave-active {
            transition: opacity 3s ease-out;
        }
        .v-enter-to {
            opacity: 1;
        }
        .v-leave-to {
            opacity: 0;
        }
    </style>
 ...


出場入場幀動畫

準備好一個keyframes,然後把它寫在v-xxx-active中即可:

···
  <style>
        @keyframes shake {
            0% {
                transform: translateX(-100px);
            }
            50% {
                transform: translateX(-50px);
            }
            100% {
                transform: translateX(50px);
            }
        }
        .v-enter-active {
            animation: shake 2s;
        }
        .v-leave-active {
            animation: shake 2s;
        }
    </style>
···


使用name=對動畫進行 片段式地 命名

可以在template中,
<transition>標籤中,用name=指定一個命名,
然後在style中定義css類時,
將之前的v-xxx-xxx等定義符換成[命名]-xxx-xxx即可:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <style>
        @keyframes shake {
            0% {
                transform: translateX(-100px);
            }
            50% {
                transform: translateX(-50px);
            }
            100% {
                transform: translateX(50px);
            }
        }
        .heheda-enter-active {
            animation: shake 2s;
        }
        .heheda-leave-active {
            animation: shake 2s;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="heheApp"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
          handleClick() {
            this.show = !this.show;
          }  
        },
        template: `
            <div>
                <transition name="heheda">
                    <div v-if="show">heheda</div>
                </transition>
                <button @click="handleClick">切換</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>
</html>


對動畫類的完全命名

即直接在template中,在<transition>標籤中,
使用[原css命名] = [新命名]的方式,對整個CSS類取別名,
用的時候,直接使用新命名即可:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <style>
        @keyframes shake {
            0% {
                transform: translateX(-100px);
            }
            50% {
                transform: translateX(-50px);
            }
            100% {
                transform: translateX(50px);
            }
        }
        .hihi {
            animation: shake 2s;
        }
        .byebye {
            animation: shake 2s;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="heheApp"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
          handleClick() {
            this.show = !this.show;
          }  
        },
        template: `
            <div>
                <transition 
                    enter-active-class="hihi"
                    leave-active-class="byebye">
                    <div v-if="show">heheda</div>
                </transition>
                <button @click="handleClick">切換</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>
</html>

關鍵代碼:

<!DOCTYPE html>
<html lang="en">
<head>
...
    <style>
        ...
        .hihi {
            animation: shake 2s;
        }
        .byebye {
            animation: shake 2s;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>

...
<script>
   ...
    template: `
       ...
                <transition 
                    enter-active-class="hihi"
                    leave-active-class="byebye">
                    <div v-if="show">heheda</div>
                </transition>
...
</script>

運行效果同上例;


完全命名的方式 使得 容易接入 第三方庫

這裏以引入Animate.css爲例;
官網:https://animate.style/
官網首頁如下,右側列表是各種動畫類型,點擊可以預覽效果:


官網簡略引導:
(如下可知,即框架已經把動畫定義實現好了,
使用時只用直接使用定義好的框架樣式命名即可)

彈跳效果:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <script src="https://unpkg.com/vue@next"></script>
    <link
        rel="stylesheet"
        href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
    />
</head>

<body>
    <div id="heheApp"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
          handleClick() {
            this.show = !this.show;
          }  
        },
        template: `
            <div>
                <transition 
                    enter-active-class="animate__animated animate__bounce"
                    leave-active-class="animate__animated animate__bounce">
                    <div v-if="show">heheda</div>
                </transition>
                <button @click="handleClick">切換</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>
</html>

閃爍效果:

template: `
            <div>
                <transition 
                    enter-active-class="animate__animated animate__flash"
                    leave-active-class="animate__animated animate__flash">
                    <div v-if="show">heheda</div>
                </transition>
                <button @click="handleClick">切換</button>
            </div>`


注意以上案例,將v-if換成v-show也是可以正常運行的

區別在於隱藏組件的底層機制不同而已,
在博客筆記《Vue3 | 條件渲染 與 列表循環渲染》我們討論過這個事情;


顏色過渡和位移 動畫 結合

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <style>
        @keyframes shake {
            0% {
                transform: translateX(-100px);
            }
            50% {
                transform: translateX(-50px);
            }
            100% {
                transform: translateX(50px);
            }
        }
        .v-enter-from {
            color: red;
        }
        .v-enter-active {
            animation: shake 2s;
            transition: all 2s ease-in;
        }
        .v-leave-active {
            color: red;
            animation: shake 2s;
            transition: all 2s ease-in;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="heheApp"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
          handleClick() {
            this.show = !this.show;
          }  
        },
        template: `
            <div>
                <transition>
                    <div v-if="show">heheda</div>
                </transition>
                <button @click="handleClick">切換</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>
</html>

關鍵代碼:
入場,從紅色開始,到黑色(默認顏色);
出場,從黑色(默認顏色)開始,到紅色;
all表示過渡特性適配到 所用類型的動畫;

        .v-enter-from {
            color: red;
        }
        .v-enter-active {
            animation: shake 2s;
            transition: all 2s ease-in;
        }
        .v-leave-active {
            color: red;
            animation: shake 2s;
            transition: all 2s ease-in;
        }


控制組合動畫時長 以某一類型動畫的時間爲準

<transition>標籤上,
寫上type="transition",則組合動畫的時長 以過渡動畫 爲準;
寫上type="animation,則組合動畫的時長 以普通類型動畫 爲準;

如下案例,寫上type="transition"
則組合動畫在 過渡動畫執行完畢(即3s)之後,
會立即停止 正在運行的 所有動畫:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <style>
        @keyframes shake {
            0% {
                transform: translateX(-100px);
            }
            50% {
                transform: translateX(-50px);
            }
            100% {
                transform: translateX(50px);
            }
        }
        .v-enter-from {
            color: red;
        }
        .v-enter-active {
            animation: shake 6s;
            transition: all 3s ease-in;
        }
        .v-leave-active {
            color: red;
            animation: shake 6s;
            transition: all 3s ease-in;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="heheApp"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
          handleClick() {
            this.show = !this.show;
          }  
        },
        template: `
            <div>
                <transition type="transition">
                    <div v-if="show">heheda</div>
                </transition>
                <button @click="handleClick">切換</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>
</html>


控制組合動畫時長 以自定義的時長爲準

<transition>標籤上,
寫上:duration="[動畫時長 / ms]",則組合動畫的時長 以這裏定義的數據 爲準,
無論CSS類中,定義了多長的時延:

 template: `
            <div>
                <transition :duration="1000">
                    <div v-if="show">heheda</div>
                </transition>
                <button @click="handleClick">切換</button>
            </div>`


分別 統一 出入場動畫的時延

:duration="[{enter: [入場動畫時延], leave:[出場動畫時延]}]"

template: `
            <div>
                <transition :duration="{enter: 1000, leave: 3000}">
                    <div v-if="show">heheda</div>
                </transition>
                <button @click="handleClick">切換</button>
            </div>`


禁用CSS動畫,使用JS動畫

-- 使用:css="false"禁用CSS動畫,使得CSS動畫都失效(如果有定義的話);
-- @before-enter = "[方法名]" 定義 入場就緒開始前 狀態的動畫回調方法;
-- @enter = "[方法名]" 定義 動畫運行時 狀態的 回調方法;
-- @after-enter="[方法名]"定義 動畫結束時 狀態的 回調方法;
-- done(); 通知架構動畫已經結束,可以回調 handleEnterEnd(el)了;
【注意,以上是入場動畫的鉤子回調,
enter換成leave,即是對應的退場動畫的鉤子回調】

如下代碼,
handleBeforeEnter(el)指定 初始動畫顏色 爲 橙色;
handleEnterActive(el, done)使得 動畫在 橙色 與 藍色之間 動態切換,
配合 setInterval(() => {}, 1000)時隔一秒切換一次;
clearInterval(animation);配合 setTimeout(() => {}, 5000)使得5秒後關閉動畫;
隨後調用done(); 通知架構 動畫已經結束,可以回調 handleEnterEnd(el)了;
handleEnterEnd(el)調試性地 彈出一個彈窗;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="heheApp"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
          handleClick() {
            this.show = !this.show;
          },  
          handleBeforeEnter(el) {
            el.style.color = "orange";
          },
          handleEnterActive(el, done) {
            const animation = setInterval(() => {
                const color = el.style.color;
                if(color === "orange") {
                    el.style.color = 'blue';
                } else {
                    el.style.color = 'orange';
                }
            }, 1000)
            setTimeout(() => {
                clearInterval(animation);
                done();
            }, 5000)
          },
          handleEnterEnd(el) {
              alert("動畫結束!!!");
          }
        },
        template: `
            <div>
                <transition 
                :css="false"
                @before-enter = "handleBeforeEnter"
                @enter="handleEnterActive"
                @after-enter="handleEnterEnd">
                    <div v-if="show">heheda</div>
                </transition>
                <button @click="handleClick">切換</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>
</html>

運行效果:


最基本的 多個 單元素標籤 切換案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>

<body>
    <div id="heheApp"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
          handleClick() {
            this.show = !this.show;
          },
        },
        template: `
            <div>
                <transition >
                    <div v-if="show">heheda</div>
                    <div v-else="show">lueluelue</div>
                </transition>
                <button @click="handleClick">切換</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>
</html>


帶上入場 退場 動畫的 兩個單元素標籤切換

-- css塊上面已經講過了,這裏主要是看mode="in-out"
這裏指定爲mode="in-out"的話,
則切換時 先進行入場節點的 入場 及其 動畫【in】,
再進行退場節點 的 入場 及其 動畫【out】;
【缺點:入場 與 退場的節點,在入場動畫完畢前,會同框】

-- 如 指定爲mode="out-in",則順序與上相反;
【特性:入場 與 退場的節點 不會同框】

-- appear特性:初始加載節點的時候,就會啓動入場動畫
沒有加這個標籤,入場動畫需要觸發纔會啓動;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <style>
        .v-leave-to {
            opacity: 0;
        }
        .v-enter-from {
            opacity: 0;
        }
        .v-enter-active,
        .v-leave-active {
            transition: opacity 2s ease-in;
        }
        .v-leave-from,
        .v-enter-to {
            opacity: 1;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="heheApp"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
          handleClick() {
            this.show = !this.show;
          },
        },
        template: `
            <div>
                <transition mode="out-in" appear>
                    <div v-if="show">heheda</div>
                    <div v-else="show">lueluelue</div>
                </transition>
                <button @click="handleClick">切換</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>
</html>


帶上入場 退場 動畫的 兩個組件 的切換

基於上例進行小改動即可,其原理是類似的,
以下代碼實現的效果 同上例;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <style>
        .v-leave-to {
            opacity: 0;
        }
        .v-enter-from {
            opacity: 0;
        }
        .v-enter-active,
        .v-leave-active {
            transition: opacity 2s ease-in;
        }
        .v-leave-from,
        .v-enter-to {
            opacity: 1;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="heheApp"></div>
</body>
<script>

    const ComponentA = {
        template: `<div>heheda</div>`
    }

    const ComponentB = {
        template: `<div>lueluelue</div>`
    }

    const app = Vue.createApp({
        data() {
            return {
                show: false
            }
        },
        methods: {
          handleClick() {
            this.show = !this.show;
          },
        },
        components: {
            'component-a': ComponentA,
            'component-b': ComponentB,
        },
        template: `
            <div>
                <transition mode="out-in" appear>
                    <component-a v-if="show"/>
                    <component-b v-else="show"/>
                </transition>
                <button @click="handleClick">切換</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>
</html>


<component>組件佔位 + is屬性 + 雙向綁定特性 實現上例效果

-- data字段 存儲要展示的子組件 的 組件名;
-- 點擊事件中 更改data字段 以 更換 展示的子組件,
同時產生組件的 入場退場,觸發相關動畫;
-- template中 使用 <component>標籤佔位,
使用is控制要展示的組件, 指定值爲 data字段;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <style>
        .v-leave-to {
            opacity: 0;
        }
        .v-enter-from {
            opacity: 0;
        }
        .v-enter-active,
        .v-leave-active {
            transition: opacity 2s ease-in;
        }
        .v-leave-from,
        .v-enter-to {
            opacity: 1;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="heheApp"></div>
</body>
<script>

    const ComponentA = {
        template: `<div>heheda</div>`
    }

    const ComponentB = {
        template: `<div>lueluelue</div>`
    }

    const app = Vue.createApp({
        data() {
            return {
                component : 'component-a'
            }
        },
        methods: {
          handleClick() {
            if (this.component === 'component-a') {
                this.component = 'component-b';
            } else {
                this.component = 'component-a';
            }
          },
        },
        components: {
            'component-a': ComponentA,
            'component-b': ComponentB,
        },
        template: `
            <div>
                <transition mode="out-in" appear>
                    <component :is="component">
                </transition>
                <button @click="handleClick">切換</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>
</html>

運行效果同上例;


列表動畫

即列表增刪元素時,產生的入場 和 出場動畫

主要是對itemViewv-for等標籤套上<transition-group>這個特殊動畫標籤,
然後點擊事件時使用unshift在隊頭添加元素,
其他的定義跟普通動畫差不多;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <style>
        .v-enter-from {
            opacity: 0;
            transform: translateY(30px);
        }
        .v-enter-active {
            transition: all .5s ease-in;
        }
        .v-enter-to {
            opacity: 1;
            transform: translateY(0);
        }
        .v-move {
            transform: all .5s ease-in;
        }
        .list-item {
            display: inline-block;
            margin-right: 10px;
        }
    </style>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="heheApp"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                list : [1, 2, 3]
            }
        },
        methods: {
          handleClick() {
            this.list.unshift(this.list.length + 1);
          },
        },
        template: `
            <div>
                <transition-group>
                    <span 
                        class="list-item" 
                        v-for="item in list"
                        :key = "item">{{item}}</span>
                </transition-group>
                <button @click="handleClick">增加</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>
</html>

運行效果:


狀態動畫

顯示一個值【狀態】 到 另外一個值【狀態】 的變化過程,
類似於Android的ValueAnimator

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World! heheheheheheda</title>
    <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
    <div id="heheApp"></div>
</body>
<script>
    const app = Vue.createApp({
        data() {
            return {
                number: 1,
                animateNumber: 1
            }
        },
        methods: {
          handleClick() {
            this.number = 10;
            const animation = setInterval(() => {
                this.animateNumber += 1;
                if(this.animateNumber >= this.number){
                    clearInterval(animation);
                }
            }, 100);
          },
        },
        template: `
            <div>
                <span>{{animateNumber}}</span>
                <button @click="handleClick">改變</button>
            </div>`
    });

    const vm = app.mount('#heheApp');
</script>
</html>

運行效果:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章