完整原文地址见简书https://cloud.tencent.com/developer/article/1811209
name=**对动画进行 片段式地 命名v-if**换成**v-show**也是可以正常运行的<component>**组件占位 + is属性 + 双向绑定特性 实现上例效果**关键帧 --- 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>-- 使用**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**为例;
官网首页如下,右侧列表是各种动画类型,点击可以预览效果:

官网简略引导:
(如下可知,即**框架**已经把**动画**定义**实现**好了,
使用时只用直接使用**定义好的框架**的**样式命名**即可)

弹跳效果:
<!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="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>运行效果同上例;
即列表增删元素时,产生的**
入场 和 出场动画**;
主要是对**itemView**、**v-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>运行效果:
