动画效果与过度效果
API文档:https://v2.cn.vuejs.org/v2/guide/transitions.html#CSS-%E5%8A%A8%E7%94%BB
单个元素
transition标签不会呈现在浏览器元素选项上,将相应动画效果的内容放置在transition标签内,并且设置相应class的样式,可以实现动画效果。
<template>
<div>
<button @click="isShow = !isShow">显示/隐藏</button>
<!--将需要增加动画效果的元素放在transition内-->
<!--如果设置name="xxx",name后面的v-enter-active的v就要改成xxx-->
<!--appear设置表示一进页面就显示动画效果-->
<!-- 如果变化元素只有一个,可以不设置name,如果有多个,为了避免样式冲突,还是设置name -->
<transition name="democss" :appear="true">
<h1 v-show="isShow">你好啊!</h1>
</transition>
</div>
</template>
<script>
export default {
name: "MyTest",
data() {
return {
isShow: true,
};
},
};
</script>
<style>
/*过度效果,标志transition*/
h1 {
background-color: aqua;
}
/*进入和离开过程*/
.v-enter-active,
.v-leave-active {
transition: 0.5s linear;
}
/*刚进入和离开过去*/
.v-enter,
.v-leave-to {
transform: translateX(-100%);
}
/*刚进入和进入过去*/
.v-leave,
.v-enter-to {
transform: translateX(0);
}
/*
下面的是用@keyframe实现的,一样的效果,动画效果,标志@keyframe,animation
h1 {
background-color: aqua;
}
.democss-enter-active { //如果没有name则为.v-enter-active
animation: testPart 1s linear;
}
.democss-leave-active {
animation: testPart 1s linear reverse;
}
@keyframes testPart {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0px);
}
}
*/
</style>
多个元素
这时候需要用transition-group标签,并且其子标签也就是要给与动画的标签需要有key值。
<template>
<div>
<button @click="isShow = !isShow">显示/隐藏</button>
<!-- transition-group的子标签有key值 -->
<transition-group :appear="true">
<h1 v-show="!isShow" key="1">你好啊!</h1>
<h1 v-show="isShow" key="2">你好啊!</h1>
</transition-group>
</div>
</template>
<script>
export default {
name: "MyTest",
data() {
return {
isShow: true,
};
},
};
</script>
<style>
h1 {
background-color: aqua;
}
.v-enter-active,
.v-leave-active {
transition: 0.5s linear;
}
.v-enter,
.v-leave-to {
transform: translateX(-100%);
}
.v-leave,
.v-enter-to {
transform: translateX(0);
}
</style>
引用第三方库
有很多动画第三方库,这里示例为animate.css
可以通过
npmjs.com
搜索得到并进入官网。里面有相应的步骤,基本就是先安装相应的类库
npm install animate.css
然后再相应的组件中导入
import "animate.css"
接着将transition的name值改为animate__animated animate__bounce,以及设置属性,示例中加的为enter-active-class和leave-active-class,相应的类可以在官网复制粘贴直接使用
<template>
<div>
<button @click="isShow = !isShow">显示/隐藏</button>
<!-- 如果变化元素只有一个,可以不设置name,如果有多个,为了避免样式冲突,还是设置name -->
<transition-group
name="animate__animated animate__bounce"
:appear="true"
enter-active-class="animate__shakeX"
leave-active-class="animate__bounceOut"
>
<h1 v-show="!isShow" key="1">你好啊!</h1>
<h1 v-show="isShow" key="2">你好啊!</h1>
</transition-group>
</div>
</template>
<script>
import "animate.css";
export default {
name: "MyTest",
data() {
return {
isShow: true,
};
},
};
</script>
<style>
h1 {
background-color: aqua;
}
</style>
todolist案例
方法一:在MyItem内改
<template>
<transition name="democss" appear>
<li>
<label>
<!-- 如下代码也能实现功能,但是不太推荐,因为有点违反原则,因为修改了props -->
<!-- <input type="checkbox" v-model="todo.done"/> -->
<input
type="checkbox"
:checked="todo.done"
@change="handleCheck(todo.id)"
/>
<span v-show="!todo.isEdit">{{ todo.title }}</span>
<input
v-show="todo.isEdit"
type="text"
:value="todo.title"
@blur="handleBlur(todo, $event)"
ref="inputPart"
/>
</label>
<button class="btn btn-danger" @click="handleDelete(todo.id)">
删除
</button>
<button
v-show="!todo.isEdit"
class="btn btn-edit"
@click="handleEdit(todo)"
>
编辑
</button>
</li>
</transition>
</template>
<script>
export default {
name: "MyItem",
props: ["todo"],
methods: {
handleCheck(id) {
//this.checkTodo(id);
this.$bus.$emit("checkTodo", id);
},
handleDelete(id) {
//this.deleteTodo(id);
this.$bus.$emit("deleteTodo", id);
},
handleEdit(todo) {
if (Object.prototype.hasOwnProperty.call(todo, "isEdit")) {
todo.isEdit = true;
} else {
this.$set(todo, "isEdit", true);
}
this.$nextTick(function () {
this.$refs.inputPart.focus();
});
},
//失去焦点回调
handleBlur(todo, e) {
todo.isEdit = false;
if (!e.target.value.trim()) return alert("输入不能为空");
this.$bus.$emit("updateTodo", todo.id, e.target.value);
},
},
};
</script>
<style scoped>
/*item*/
li {
list-style: none;
height: 36px;
line-height: 36px;
padding: 0 5px;
border-bottom: 1px solid #ddd;
}
li label {
float: left;
cursor: pointer;
}
li label li input {
vertical-align: middle;
margin-right: 6px;
position: relative;
top: -1px;
}
li button {
float: right;
display: none;
margin-top: 3px;
}
li:before {
content: initial;
}
li:last-child {
border-bottom: none;
}
li:hover {
background-color: #ddd;
}
li:hover button {
display: block;
}
.democss-enter-active {
animation: testPart 1s linear;
}
.democss-leave-active {
animation: testPart 1s linear reverse;
}
@keyframes testPart {
from {
transform: translateX(100%);
}
to {
transform: translateX(0px);
}
}
</style>
方法二: 在MyList中修改
由于使用了v-for因此这时候需要用transition-group
<template>
<ul class="todo-main">
<transition-group name="democss" appear>
<MyItem v-for="todo in todos" :key="todo.id" :todo="todo" />
</transition-group>
</ul>
</template>
<script>
import MyItem from "./MyItem";
export default {
name: "MyList",
components: { MyItem },
props: ["todos"],
};
</script>
<style scoped>
/*main*/
.todo-main {
margin-left: 0px;
border: 1px solid #ddd;
border-radius: 2px;
padding: 0px;
}
.todo-empty {
height: 40px;
line-height: 40px;
border: 1px solid #ddd;
border-radius: 2px;
padding-left: 5px;
margin-top: 10px;
}
.democss-enter-active {
animation: testPart 1s linear;
}
.democss-leave-active {
animation: testPart 1s linear reverse;
}
@keyframes testPart {
from {
transform: translateX(100%);
}
to {
transform: translateX(0px);
}
}
</style>
感觉第二种情况更加清晰点。