原生动画
在Vue中实现动画,与原生中实现是没有任何区别的
使用js自己实现
用css实现
用第三库实现
js动画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 100px;
height: 100px;
background-color: red;
}
.box2 {
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<div id="app">
<button @click="animate">按钮</button>
<div class="box" ref="box"></div>
</div>
<script src="./js/vue.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
/**
* js
*/
// let app = new Vue({
// el: '#app',
// methods: {
// animate() {
// // console.log( $(this.$refs.box) ); jq对象
// $(this.$refs.box).animate({
// width: 200,
// height: 200
// }, function() {
// console.log('动画完成');
// })
// }
// }
// });
</script>
</body>
</html>
css动画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 100px;
height: 100px;
background-color: red;
transition: all 1s;
/* 所有样式发生改变,触发动画 */
}
.box2 {
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<div id="app">
<button @click="animate">按钮</button>
/* <div class="box" ref="box"></div> */
<hr />
<div class="box" :class="{box2: animated}"></div>
</div>
<script src="./js/vue.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
animated: false
},
methods: {
animate() {
// $(this.$refs.box).addClass('box2');
this.animated = !this.animated;
}
}
});
</script>
</body>
</html>
vue动画
自己实现的vue动画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 100px;
height: 100px;
background-color: red;
/* transition: all 1s; */
}
.box2 {
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<div id="app">
<button @click="animate">按钮</button>
<div class="box" v-if="isShow" ref="box"></div>
</div>
<script src="./js/vue.js"></script>
<script>
/**
transition 组件
Vue 为我们在使用过程以下几个特殊情况提供一套动画模式
- 条件渲染 (使用 `v-if`)
- 条件展示 (使用 `v-show`)
- 动态组件
- 组件根节点
*/
let app = new Vue({
el: '#app',
data: {
isShow: false
},
methods: {
animate() {
this.isShow = !this.isShow;
// 1. 报错 this.$refs.box 为undefined
console.log(this.$refs.box)
this.$refs.box.classList.add('box2');
// 2. 不报错 但没动画效果
// 渲染的过程也有一个异步的过程
// this.$nextTick(() => {
// this.$refs.box.classList.add('box2');
// });
// 3. 正常
// this.$nextTick(() => {
// setTimeout(() => {
// this.$refs.box.classList.add('box2');
// }, 0);
// });
}
}
});
// 解析3的原因
// let box1 = document.createElement('div');
// 1.无效果
// box1.classList.add('box2');
// document.body.appendChild( box1 );
// 2.无效果
// 页面渲染的一瞬间,就已经存在box2了
// box1.classList.add('box2');
// ------------------------------------------------------------
// 以上代码为宏任务,执行完后去渲染,完了再执行定时器里的东西
// 3. 正常
// 根据上面代码的结果再一次性的去渲染页面
// 渲染丢到下一组任务中去
// 定时器 下一轮的宏任务中执行
// setTimeout(() => {
// box1.classList.add('box2');
// }, 0);
</script>
</body>
</html>
vue动画 - trasition
/**
transition 组件
Vue 为我们在使用过程以下几个特殊情况提供一套动画模式
- 条件渲染 (使用 `v-if`)
- 条件展示 (使用 `v-show`)
- 动态组件
- 组件根节点
*/
栗子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 100px;
height: 100px;
background-color: red;
/* transition: all 1s; */
}
.box2 {
width: 200px;
height: 200px;
}
/* 运动周期中一直存在 */
.slide-fade-enter-active, .slide-fade-leave-active {
transition: all 1s ease;
}
/* 初始化的时候存在 */
.slide-fade-enter {
width: 0;
height: 0;
}
/* 运动周期中一直存在 */
.slide-fade-enter-to {
width: 100px;
height: 100px;
}
/* 离开的起点和进入的终点一直,可以合并 */
.slide-fade-leave {
/*可以和slide-fade-enter-to合并*/
width: 100px;
height: 100px;
}
.slide-fade-leave-to {
/*可以和slide-fade-enter合并*/
width: 0;
height: 0;
}
</style>
</head>
<body>
<div id="app">
<button @click="animate">按钮</button>
<!-- 找以 slide-fade 为前缀的样式 -->
<transition name="slide-fade">
<div class="box" v-if="isShow" ref="box"></div>
</transition>
</div>
<script src="./js/vue.js"></script>
<script>
let app = new Vue({
el: '#app',
data: {
isShow: false
},
methods: {
animate() {
this.isShow = !this.isShow;
// vue 解决了这个问题
// this.$nextTick(() => {
// setTimeout(() => {
// this.$refs.box.classList.add('box2');
// }, 0);
// });
}
}
});
</script>
</body>
</html>
生命周期钩子函数
Vue 会在动画开始到结束的不同阶段中触发对应的一些钩子(事件)。
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:after-enter="afterEnter"
v-on:enter-cancelled="enterCancelled"
v-on:before-leave="beforeLeave"
v-on:leave="leave"
v-on:after-leave="afterLeave"
v-on:leave-cancelled="leaveCancelled"
>
</transition>
// ...
methods: {
// --------
// 进入中
// --------
beforeEnter: function (el) {
// ...
},
// 当与 CSS 结合使用时
// 回调函数 done 是可选的
enter: function (el, done) {
// ...
done()
},
afterEnter: function (el) {
// ...
},
enterCancelled: function (el) {
// ...
},
// --------
// 离开时
// --------
beforeLeave: function (el) {
// ...
},
// 当与 CSS 结合使用时, 回调函数 done 是可选的,会自动监听transitionend
// 如果不是css动画 手动done
leave: function (el, done) {
// ...
done()
},
afterLeave: function (el) {
// ...
},
// leaveCancelled 只用于 v-show 中
leaveCancelled: function (el) {
// ...
}
}
当与 CSS 结合使用时, 回调函数 done 是可选的,会自动监听transitionend。当只用 JavaScript 过渡的时候,在
enter
和leave
中必须使用done
进行回调。否则,它们将被同步调用,过渡会立即完成。
插件
如果一个三方库需要对Vue进行扩展,不推荐直接全局这么写, Vue 提供了一个规范化的接口去对其进行扩展
/ 1. 导出一个函数 执行
// export default function(_Vue, options) {
// }
// 2. 导出一个对象,对象下必须有一个install, install方法会执行
// export default {
// install(_Vue, options) {
// _Vue.prototype.getData = function() {
// console.log('getData 获取数据');
// }
// }
// }
// 3. 导出一个class 还是会转成函数
export default class KKB {
static f(_Vue, options) {
_Vue.prototype.getData = function() {
console.log('getData 获取数据');
}
}
install(_Vue, options) {
_Vue.prototype.getData = function() {
console.log('getData 获取数据');
}
}
}
// Vue.use( KKB.f, {
// a: 1
// } );
Vue.use( new KKB, {
a: 1
} );