前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue3 | 动画专题

Vue3 | 动画专题

作者头像
凌川江雪
发布2021-04-09 15:39:46
1.3K0
发布2021-04-09 15:39:46
举报
文章被收录于专栏:李蔚蓬的专栏李蔚蓬的专栏

完整原文地址见简书https://cloud.tencent.com/developer/article/1811209

本文内容提要

  • 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 为关:

代码语言:javascript
复制
<!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:

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

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

运行时产生动画:

可以配合按钮和点击事件,动态 交互地 开关动画:

代码语言:javascript
复制
<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类实例**即可;

-- 可以准备一个**触发事件**,在事件中**反转**两个背景颜色值,由此可实现过渡动画:

代码语言:javascript
复制
<!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字段的值**改变背景颜色;

代码语言:javascript
复制
<!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节点即可;

代码语言:javascript
复制
<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**表示出场动画的**结束时**的透明度;**

其余步骤 同入场动画:

代码语言:javascript
复制
<!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**相同(一般都是相同的),那也可以省略它;

以下代码实现的效果,同上:

代码语言:javascript
复制
...
        <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**中即可:

代码语言:javascript
复制
···
  <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**即可:

代码语言:javascript
复制
<!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类取别名,

用的时候,直接使用新命名即可:

代码语言:javascript
复制
<!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>

关键代码:

代码语言:javascript
复制
<!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/

官网首页如下,右侧列表是各种动画类型,点击可以预览效果:

官网简略引导:

(如下可知,即**框架**已经把**动画**定义**实现**好了,

使用时只用直接使用**定义好的框架**的**样式命名**即可)

弹跳效果:

代码语言:javascript
复制
<!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>

闪烁效果:

代码语言:javascript
复制
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 | 条件渲染 与 列表循环渲染》我们讨论过这个事情;

颜色过渡和位移 动画 结合
代码语言:javascript
复制
<!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**表示**过渡特性**适配到 所用类型的动画;**

代码语言:javascript
复制
        .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)之后,

会立即停止 正在运行的 所有动画:

代码语言:javascript
复制
<!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类中,定义了多长的时延:

代码语言:javascript
复制
 template: `
            <div>
                <transition :duration="1000">
                    <div v-if="show">heheda</div>
                </transition>
                <button @click="handleClick">切换</button>
            </div>`
分别 统一 出入场动画的时延

:duration="[{enter: [入场动画时延], leave:[出场动画时延]}]"

代码语言:javascript
复制
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)**调试性地 弹出一个弹窗;**

代码语言:javascript
复制
<!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>

运行效果:

最基本的 多个 单元素标签 切换案例
代码语言:javascript
复制
<!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**特性:初始加载节点的时候,就会启动**入场动画**,**

没有加这个标签,**入场动画**需要触发才会启动;

代码语言:javascript
复制
<!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>
带上入场 退场 动画的 两个组件 的切换

基于上例进行小改动即可,其原理是类似的,

以下代码实现的效果 同上例;

代码语言:javascript
复制
<!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**字段;**

代码语言:javascript
复制
<!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>

运行效果同上例;

列表动画

即列表增删元素时,产生的**入场 和 出场动画**;

主要是对**itemView**、**v-for**等标签套上**<transition-group>**这个特殊动画标签,

然后点击事件时使用**unshift**在队头添加元素,

其他的定义跟普通动画差不多;

代码语言:javascript
复制
<!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**;

代码语言:javascript
复制
<!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>

运行效果:

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 本文内容提要
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档