Vue 在插入、更新或者移除DOM 时,提供多种不同方式的应用过渡效果。包括以下方式:
1、给需要运动的元素加入transition标签
<transition>
需要运动的元素
</transition>
2、默认情况下如果控制了transition标签元素的显示和隐藏它会默认给这个元素加入一些class
隐藏:加入类名:
v-leave :定义离开过渡的开始状态。
v-leave-active :定义离开过渡生效时的状态。
v-leave-to :定义离开过渡的结束状态。
显示:加入类名:
v-enter: 准备进行运动的状态(起始状态)
v-enter-active: 整个运动状态
v-enter-to: 整个运动状态(强调运动的结果,结束状态)
3、将来如果给transition设置一个name为“show”以后,将来所有的类的名称都需要改变,默认前缀为v- 如果加入了name属性,需要将v- 改为show-
示例:
- <style>
- .fade-enter-active, .fade-leave-active {
- transition: opacity .5s;
- }
- .fade-enter, .fade-leave-to{
- opacity: 0;
- }
- </style>
- <div id="demo">
- <button v-on:click="show = !show">
- Toggle
- </button>
- <transition name="fade">
- <p v-if="show">hello</p>
- </transition>
- </div>
- <script>
- new Vue({
- el: '#demo',
- data: {
- show: true
- }
- })
- </script>
当插入或删除包含在 transition 组件中的元素时,Vue 将会做以下处理:
(1)自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名。
(2)如果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用。
(3)如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作 (插入/删除) 在下一帧中立即执行。(注意:此指浏览器逐帧动画机制,和 Vue 的 nextTick 概念不同)
对于这些在过渡中切换的类名来说,如果使用一个没有名字的 <transition>,则 v- 是这些类名的默认前缀。如果你使用了 <transition name="my-transition">,那么 v-enter 会替换为 my-transition-enter。
v-enter-active 和 v-leave-active 可以控制进入/离开过渡的不同的缓和曲线
二、利用animate.css结合transition实现动画
可以通过以下 attribute 来自定义过渡类名:
enter-class
enter-active-class
enter-to-class (2.1.8+)
leave-class
leave-active-class
leave-to-class (2.1.8+)
它们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库,如 Animate.css 结合使用十分有用。
- <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
- <div id="example-3">
- <button @click="show = !show">
- Toggle render
- </button>
- <transition
- name="custom-classes-transition"
- enter-active-class="animated tada"
- leave-active-class="animated bounceOutRight"
- >
- <p v-if="show">
- 明月几时有,把酒问青天。
- </p>
- </transition>
- </div>
- <script>
- new Vue({
- el: '#example-3',
- data: {
- show: true
- }
- })
- </script>
三、利用 vue中的钩子函数实现动画
- <style>
- .show {
- transition: all 0.5s;
- }
- </style>
- <div id="app">
- <button @click="toggle">显示/隐藏</button><br>
- <transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
- <div class="show" v-show="isshow">
- 明月几时有?把酒问青天
- </div>
- </transition>
- </div>
- <script>
- new Vue({
- el: '#app',
- data: {
- isshow: false
- },
- methods: {
- toggle: function () {
- this.isshow = !this.isshow;
- },
- beforeEnter: function (el) {
- console.log("beforeEnter");
- // 当入场之前会执行 v-enter
- el.style = "padding-left:100px";
- },
- enter: function (el, done) {
- // 当进行的过程中每执行 v-enter-active
- console.log("enter");
- // 为了能让代码正常进行,在设置了结束状态后必须调用一下这个元素的
- // offsetHeight / offsetWeight 只是为了让动画执行
- el.offsetHeight;
- // 结束的状态最后写在enter中
- el.style = "padding-left:0px";
- // 执行done继续向下执行
- done();
- },
- afterEnter: function (el) {
- // 当执行完毕以后会执行
- console.log("afterEnter");
- //this.isshow = false;
- }
- }
- })
- </script>
四、综合案例
1、View代码
- <div id="app">
- <div class="add">
- 编号: <input id="id" v-color="color" v-focus type="text" v-model="id">
- 品牌名称: <input v-model="name" type="text">
- <button @click="add">添加</button>
- </div>
-
- <div>
- <table class="tb">
- <tr>
- <th>编号</th>
- <th>品牌名称</th>
- <th>创立时间</th>
- <th>操作</th>
- </tr>
- <tr v-if="list.length <= 0">
- <td colspan="4">没有品牌数据</td>
- </tr>
- <!--加入: key="index" 时候必须把所有参数写完整 -->
- <tr v-for="(item,key,index) in list" :key="index">
- <td>{{item.id}}</td>
- <td>{{item.name}}</td>
- <td>{{item.ctime | dateFrm("/")}}</td>
- <!-- 使用vue来注册事件时,我们在dom元素中是看不到的 -->
- <td><a href="javascript:void(0)" @click="del(item.id)">删除</a></td>
- </tr>
- </table>
- </div>
-
- <transition
- @before-enter="beforeEnter"
- @enter="enter"
- @after-enter ="afterEnter"
- @before-leave="beforeLeave"
- @leave="leave"
- @after-leave ="afterLeave"
- >
- <div class="del" v-show="isshow">
- <ul>
- <li>您确定要删除当前数据吗</li>
- <li>
- <button @click="delById">确定</button>
- <button @click="showClose">关闭</button>
- </li>
- </ul>
- </div>
- </transition>
- </div>
2、Model代码
- // 使用全局过滤器(公有过滤器)
- Vue.filter("dateFrm", function (time,spliceStr) {
- // return "2017-11-16";
- var date = new Date(time);
- //得到年
- var year = date.getFullYear();
- // 得到月
- var month = date.getMonth() + 1;
- // 得到日
- var day = date.getDate();
- return year + spliceStr + month + spliceStr + day;
- });
- // 先将自定义指令定义好
- // directive有两个参数
- //参数一: 自定义指令 v-focus
- //参数二: 对象,对象中可以添加很多方法
- // 添加一个inserted方法:而这个方法中又有两个参数:
- //参数一:el 当前使用自定义指令的对象
- //参数二:obj 是指它(v-color="color" )后面设置的表达式
- //{expression:"color",value:"red",}
- Vue.directive("focus", {
- inserted: function (el, obj) {
- // console.log(el);
- el.focus();
- }
- });
- Vue.directive("color", {
- inserted: function (el, obj) {
- // obj.style.color = "red";
- obj.style.color = obj.value;//????????????
- console.log(obj.value);
- }
- });
- var vm = new Vue({
- el: "#app",
- data: {
- delId:"",// 用来将要删除数据的id进行保存
- isshow:false,
- color: "green",
- id: 0,
- name: '',
- list: [
- { "id": 1, "name": "德云IT学苑", "ctime": Date() },
- { "id": 2, "name": "西安邮电大学", "ctime": Date() }
- ]
- },
- // mounted(){
- // this.getFocus()
- // },
- methods: {
- add: function () {
- //将id和namepush到list数组中
- this.list.push({ "id": this.id, "name": this.name, "ctime": Date() });
- },
- del: function (id) {
- this.isshow = true;
- // 将得到的id保存到delId里面
- this.delId = id;
- },
- beforeEnter:function(el) {
- el.style.left = "100%";
- },
- enter:function(el,done) {
- el.offsetHeight;
- el.style.left = "35%";
- },
- afterEnter:function(el){
- },
- beforeLeave:function(el){
- el.style.left = "35%";
- },
- leave:function(el,done){
- el.offsetHeight;
- el.style.left = "100%";
- setTimeout(function(){
- done();
- },500);
- },
- afterLeave:function(el){
- },
- showClose:function(el){
- this.isshow = false;
- },
- delById:function() {
- _this = this;
- // 根据DelId删除对应的数据
- var index = this.list.findIndex(function(item){
- return item.id ==_this.delId;
- });
- this.list.splice(index,1);
- // 关闭删除框
- this.isshow = false;
- }
- }
- });
3、CSS代码
- #app {
- width: 600px;
- margin: 10px auto;
- }
-
- .tb {
- border-collapse: collapse;
- width: 100%;
- }
- .tb th {
- background-color: #0094ff;
- color: white;
- }
- .tb td,
- .tb th {
- padding: 5px;
- border: 1px solid black;
- text-align: center;
- }
- .add {
- padding: 5px;
- border: 1px solid black;
- margin-bottom: 10px;
- }
- .del li{
- list-style: none;
- padding: 10px;
- }
- .del{
- position: absolute;
- top:45%;
- left: 45%;
- width: 300px;
- border: 1px solid rgba(0,0,0,0.2);
- transition: all 0.5s;
- }