今日总结
一、VUE生命周期
1、什么是生命周期
从vue示例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件统称为生命周期
2、vue生命周期钩子函数
每个 vue 实例在被创建时都要经过一系列的初始化过程
生命周期函数 = 生命周期事件 = 生命周期钩子
3、vue生命周期
详解
一共8个生命周期函数:
beforeCreate:表示,刚初始化了一个 Vue 空的实例化对象,这个时候,这个对象身上,只有默认的一些生命周期函数和默认的事件,其他东西都未创建。注意:在beforeCreate生命周期函数执行的时候,data和methods中的数据都还没有初始化。一般用于页面重定向
created:在 created 中,data和methods都已经被初始化好了。如果要调用methods中的方法,或者操作data中的数据,最早,只能在created中操作 一般用于接口请求 + 数据初始化
beforeMount:此函数在执行的时候,模板已经在内存中编译好了(虚拟DOM)。但是尚未挂载到页面中去,此时,页面还是旧的
mounted:这一步,将内存中编译好的模板,真实的替换到浏览器的页面中去。如果要通过某些插件操作页面上的DOM节点了。最早要在mounted中进行。只要执行完了mounted,就表示整个Vue实例已经初始化完毕了;此时,组件已经脱离了拆昂见阶段,进入到了运行阶段
beforeUpDate:当执行beforeUpdate的时候,页面中显示的数据还是旧的,此时,data数据是最新的,页面上为和最新的数据保持同步
updated:该事件执行的时候,页面和data数据已经保持同步了,都是最新的
beforeUpDate 和 updated 是组件运行阶段的生命周期函数,只有这两个,这两个事件会根据data数据的改变,有选择性地触发0次到多次(页面初始化的时候不会触发)
beforeDestroy:当执行beforeDestroy钩子函数的时候,Vue实例就已经从运行阶段进入到了销毁阶段,当执行beforeDestroy的时候,实例身上所有的data和所有的methods,以及过滤器、指令…… 都处于可用状态。此时。还没有真正执行销毁的过程
destroyed:当执行到该函数时,组件已经被完全销毁了,此时,组件中所有的数据、方法、指令、过滤器……都已经不可用了
由官方文档给出的生命周期图示,可以看出:
// 当 Vue 对象中没有写 el 时,可以在使用下面方法使用 可以搭配定时器使用
// vm.$mount('#app')
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>生命周期</title>
</head>
<body>
<div id="app">
<div>{{msg}}</div>
<input type="text" v-model="msg">
</div>
</body>
<script>
let vm = new Vue({
el:'#app',
data:{
msg:'hello world!'
},
methods:{},
// 生命周期
// 初始化尚未完成,data数据,methods方法都未挂载在vue实例中
// 一般用于页面重定向
beforeCreate(){
console.log('beforeCreate');
console.log(this.msg);
},
// 第一个能操作data数据的生命周期,
// 一班用于接口请求 + 数据初始化
created(){
console.log('created');
console.log(this.msg);
},
// 虚拟dom挂载前,此时页面元素尚未更新
beforeMount(){
console.log('beforeMount');
// debugger
},
// dom元素挂载之后,如果需要操作dom,可以在此生命周期执行
mounted(){
console.log(mounted);
},
// 初次加载页面时不会加载,可以执行 0次到多次
beforeUpdate(){
console.log(beforeUpdate);
},
updated(){
console.log(updated);
}
})
// 当 Vue 对象中没有写 el 时,可以在使用下面方法使用 可以搭配定时器使用
// vm.$mount('#app')
</script>
</html>
二、VUE1的请求方式:vue-resource的使用
1、安装方法
使用cdn/本地文件
注意:vue-resource文件是依赖vue文件的,注意引入顺序要在引入的vue文件下面
2、get请求
this.$http.get(url).then(res=>{})
3、post请求
this.$http.post(url,data,xxx).then(res=>{})
post 请求体格式转换时 xxx 为 { emulateJSON : true },不需要转换就不用写
示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>vue1请求方式</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 注意引入顺序 -->
<script src="./lib/vue-resource-1.3.4.js"></script>
<style>
dl{
width: 1200px;
margin: auto;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
dt{
width: 19%;
}
img{
width:100%;
height: 120px;
}
</style>
</head>
<body>
<div id="app">
<div v-for="item in carouselList" :key="item.id">
<img :src="item.imgUrlPc" alt="" />
</div>
<section>
<dl>
<dt v-for="item in courseList" :key="item.id">
<img :src="item.bannerFileUrl" alt="">
<div>{{item.courseTitle}}</div>
<p>{{item.learningNum}}人在学习</p>
<p>免费</p>
</dt>
</dl>
</section>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
baseUrl:'http://1.117.81.216:8086',
carouselList:[],
courseList:[],
},
methods: {},
created() {
// 轮播图数据
this.$http.get(this.baseUrl+'/weChat/applet/course/banner/list').then(res=>{
console.log(res);
this.carouselList = res.data.data
})
// 免费课程
this.$http.post(this.baseUrl+'/weChat/applet/course/list/type',{
type:'free',
pageNum:'1',
pageSize:'10',
}, { emulateJSON: true }).then(res=>{
console.log(res);
console.log(this);
console.log(this.courseList);
this.courseList = res.data.rows
console.log(this.courseList);
})
// 课程列表
this.$http.post(this.baseUrl+'/weChat/applet/subject/list',{enable:1}).then(res=>{
console.log(res);
})
},
});
</script>
</body>
</html>
三、VUE2.x的请求方式:axios的使用
1、安装方法
cdn/本地文件
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
2、get请求
axios.get(url).then(res=>{})
3、post请求
axios.post(url,data).then(res=>{})
post需要什么数据类型的数据就去创建一个,只有两个参数
创建符合要求的对象
let formatdata = new FormData() // formdata类型的
formdata.append(key,value)
let formurl = new URLSearchParams()
formurl.append(key,value)
示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>vue2.x请求方式</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
<style>
dl {
width: 1200px;
margin: auto;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
dt {
width: 19%;
}
img {
width: 100%;
height: 120px;
}
</style>
</head>
<body>
<div id="app">
<div v-for="item in carouselList" :key="item.id">
<img :src="item.imgUrlPc" alt="" />
</div>
<section>
<dl>
<dt v-for="item in courseList" :key="item.id">
<img :src="item.bannerFileUrl" alt="" />
<div>{{item.courseTitle}}</div>
<p>{{item.learningNum}}人在学习</p>
<p>免费</p>
</dt>
</dl>
<h2>精品课程</h2>
<dl>
<dt v-for="item in boutiqueCourseList" :key="item.id">
<img :src="item.coverFileUrl" alt="" />
<div>{{item.courseTitle}}</div>
<p>{{item.learningNum}}学习</p>
<p v-if="item.isFree == 1">免费</p>
<p v-if="item.isDiscount == 1">
<del>{{item.coursePrice}} </del> {{item.discountPrice}}
</p>
<p v-else>{{item.coursePrice}}</p>
</dt>
</dl>
</section>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
baseUrl: "http://1.117.81.216:8086",
carouselList: [],
courseList: [],
boutiqueCourseList: [],
},
methods: {
// 请求课程列表
getCourseList(type = "free", pageSize = 1, pageNum = 10) {
let formurl = new URLSearchParams();
formurl.append("type", type);
formurl.append("pageNum", pageSize);
formurl.append("pageSize", pageNum);
// post请求
return axios.post( this.baseUrl + "/weChat/applet/course/list/type", formurl);
},
},
created() {
// 轮播图数据
axios.get(this.baseUrl + "/weChat/applet/course/banner/list")
.then((res) => {
console.log(res);
this.carouselList = res.data.data;
});
// 免费课程
this.getCourseList('free',1,10).then((res) => {
console.log(res);
this.courseList = res.data.rows
});
// 精品课程
this.getCourseList('boutique',1,5).then((res) => {
console.log(res);
this.boutiqueCourseList = res.data.rows
});
// 课程列表
axios.post(this.baseUrl + "/weChat/applet/subject/list", { enable: 1 })
.then((res) => {
console.log(res);
});
},
});
</script>
</body>
</html>
请求中的异步问题:
vm.$nextTick( [callback] )
参数:
{Function} [callback]
用法:
将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。
示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
<link rel="stylesheet" href="./package/swiper-bundle.min.css">
<script src="./package/swiper-bundle.min.js"></script>
<style>
*{
margin: 0;
padding: 0;
}
/************************轮播图开始**********************/
.swiper-container > .swiper-wrapper {
width: 100%;
height: 400px;
}
.swiper-container > .swiper-wrapper > .swiper-slide {
width: 100%;
height: 100%;
background-position: 50%;
background-size: cover;
}
/***********************轮播图结束************************/
</style>
</head>
<body>
<div id="app">
<!-- 轮播图 -->
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="item in carouselList" :key="item.id" :style="'background-image:url('+item.imgUrlPc+')'"></div>
</div>
<!-- 导航按钮 -->
<div class="swiper-button-next"></div>
<div class="swiper-button-prev"></div>
<!-- 分页器 -->
<div class="swiper-pagination"></div>
</div>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
baseUrl:'http://1.117.81.216:8086',
carouselList:[],
},
methods: {},
created() {
// 轮播图数据
axios.get(this.baseUrl+'/weChat/applet/course/banner/list').then(res=>{
console.log(res);
this.carouselList = res.data.data
// 咋下次DOM更新循环结束之后执行延迟回调。再修改数据之后立即使用这个方法,获取更新后的DOM
this.$nextTick(() => {
var mySwiper = new Swiper('.swiper-container', {
direction: 'horizontal',
loop: true,
autoplay: {
delay: 5000,
stopOnLastSlide: false,
disableOnInteraction: true,
},
pagination: {
el: '.swiper-pagination',
},
// 如果需要前进后退按钮
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
})
})
})
// 免费课程
let formurl = new URLSearchParams()
formurl.append('type','free')
formurl.append('pageNum','1')
formurl.append('pageSize','10')
axios.post(this.baseUrl+'/weChat/applet/course/list/type',formurl).then(res=>{
console.log(res);
})
// 课程列表
axios.post(this.baseUrl+'/weChat/applet/subject/list',{enable:1}).then(res=>{
console.log(res);
})
},
});
</script>
</body>
</html>
四、VUE中的动画
1、使用过渡类名
.v-enter \ .v-enter-to \ .v-enter-active \ .v-leave \ .v-leave-to \ .v-leave-active
使用多个过渡时,在 <transition>标签中加上name属性,并把过渡类名中的 v- 转化为 name名-
示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
.box{
width: 500px;
height: 200px;
border: green;
border-radius: 30px;
margin: 10px auto;
background-color: skyblue;
color: #fff;
font-size: 30px;
line-height: 200px;
text-align: center;
}
.v-enter{
opacity: 0;
transform: translateX(200px);
}
.v-enter-to,
.v-leave{
opacity: 1;
transform: translateX(0px);
}
.v-enter-active,
.v-leave-active{
transition: all 2s;
}
.v-leave-to{
opacity: 0;
transform: translateX(-200px);
}
.wr-enter{
opacity: 0;
transform: translateX(-200px);
}
.wr-enter-to,
.wr-leave{
opacity: 1;
transform: translateX(0px);
}
.wr-enter-active,
.wr-leave-active{
transition: all 2s;
}
.wr-leave-to{
opacity: 0;
transform: translateX(200px);
}
</style>
</head>
<body>
<div id='app'>
<button @click="flag = !flag">点我</button>
<transition>
<div class="box" v-show="flag">{{msg}}</div>
</transition>
<transition name="wr">
<div class="box" v-show="flag">{{msg}}</div>
</transition>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
flag:true,
msg:'今天天气真不错'
},
methods: {
},
})
</script>
</body>
</html>
2、使用第三方css动画
animate.css
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css"/>
4版本的类名前要加上 animate__ 其他使用方法不变
示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css"/>
<style>
p{
margin: 100px auto;
width: 500px;
height: 100px;
text-align: center;
line-height: 100px;
font-size: 50px;
color: #fff;
background-color: rgb(162, 226, 252);
}
</style>
</head>
<body>
<div id="app">
<button @click="show = !show">Toggle render</button>
<transition
name="custom-classes-transition"
enter-active-class="animated bounceInDown"
leave-active-class="animated flipOutX"
>
<p v-if="show">hello</p>
</transition>
</div>
<script>
const vm = new Vue({
el: "#app",
data: {
show: true,
},
methods: {},
});
</script>
</body>
</html>
3、使用动画钩子函数
定义 transition 组件以及三个钩子函数
<div id="app">
<input type="button" value="切换动画" @click="isshow = !isshow">
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter">
<div v-if="isshow" class="show">OK</div>
</transition>
</div>
定义三个methods钩子方法
el.offsetWidth; // 必须要写
done(); // 必须要写
methods: {
beforeEnter(el) { // 动画进入之前的回调
el.style.transform = 'translateX(500px)';
},
enter(el, done) { // 动画进入完成时候的回调
el.offsetWidth; // 必须要写
el.style.transform = 'translateX(0px)';
done(); // 必须要写
},
afterEnter(el) { // 动画进入完成之后的回调
this.isshow = !this.isshow;
}
}
定义动画过度市场和样式
.show{
transition: all 0.4s ease;
}
4、v-for的列表过渡
定义过渡样式
定义DOM结构,其中,需要使用transition-group组件把v-for循环的列表包裹起来
定义VM中的结构
示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
/* .box{
width: 500px;
height: 200px;
border: green;
border-radius: 30px;
margin: 10px auto;
background-color: skyblue;
color: #fff;
font-size: 30px;
line-height: 200px;
text-align: center;
} */
.v-enter{
transform: translateX(-200px);
}
.v-enter-to,
.v-leave{
transform: translateX(0px);
}
.v-enter-active,
.v-leave-active{
transition: all 2s;
}
.v-leave-to{
transform: translateX(200px);
}
</style>
</head>
<body>
<div id='app'>
<button @click="flag = !flag">点我</button>
<transition-group tag="ul">
<div v-if="flag" v-for="item in 9" :key="item">
{{item}}
</div>
</transition-group>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
flag:true,
},
methods: {
},
})
</script>
</body>
</html>
5、列表的排序过渡
transition-group组件还有一个特殊之处。不仅可以进入和离开动画,还可以改变定位。要是用这个新功能只需要了解新增的 v-move 特性,他会在元素改变定位的过程中应用
v-move 和 v-leave-active 结合使用,能够让列表的过渡变得更加平缓柔和
.v-move{
transition: all 0.8s ease;
}
.v-leave-active{
position: absolute;
}
示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
.box{
width: 500px;
/* margin: 10px auto; */
}
.v-enter{
transform: translateX(-200px);
}
.v-enter-to,
.v-leave{
transform: translateX(0px);
}
.v-enter-active,
.v-leave-active{
transition: all 2s;
position: absolute;
}
.v-leave-to{
transform: translateX(200px);
}
.v-move{
transition: all 2s ease;
}
</style>
</head>
<body>
<div id='app'>
<button @click="flag = !flag">点我1</button>
<button @click="changeList">点我2</button>
<transition-group tag="ul">
<div class="box" v-if="flag" v-for="item in list" :key="item">
{{item}}
</div>
</transition-group>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
flag:true,
list:[4,5,6,7,8]
},
methods: {
changeList(){
this.list.push(this.list[this.list.length-1]+1)
}
},
})
</script>
</body>
</html>
其他
1、过渡和动画的区别
过渡:两个状态之间转化
动画:多个状态之间转化
2、JSON.stringify深拷贝时弊端:只能拷贝一层
3、http 8种请求方式
4、IP和域名 映射关系
5、post传参常见的格式:json(字符串、对象) form-url form-data
6、发送请求:url + 地址(协议(http,https)+ 主机(公网IP,域名)+路径+参数)
8种常见的请求方式 post get delete head ……
7、
<Transition> 组件#
<Transition> 是一个内置组件,这意味着它在任意别的组件中都可以被使用,无需注册。它可以将进入和离开动画应用到通过默认插槽传递给它的元素或组件上。进入或离开可以由以下的条件之一触发:
由 v-if 所触发的切换
由 v-show 所触发的切换
由特殊元素 <component> 切换的动态组件
来自 <Transition | Vue.js>
8、
可以通过监听 <Transition> 组件事件的方式在过渡过程中挂上钩子函数:
html
<Transition @before-enter="onBeforeEnter" @enter="onEnter" @after-enter="onAfterEnter" @enter-cancelled="onEnterCancelled" @before-leave="onBeforeLeave" @leave="onLeave" @after-leave="onAfterLeave" @leave-cancelled="onLeaveCancelled"> <!-- ... --></Transition>
js
export default { // ... methods: { // 在元素被插入到 DOM 之前被调用 // 用这个来设置元素的 "enter-from" 状态 onBeforeEnter(el) {}, // 在元素被插入到 DOM 之后的下一帧被调用 // 用这个来开始进入动画 onEnter(el, done) { // 调用回调函数 done 表示过渡结束 // 如果与 CSS 结合使用,则这个回调是可选参数 done() }, // 当进入过渡完成时调用。 onAfterEnter(el) {}, onEnterCancelled(el) {}, // 在 leave 钩子之前调用 // 大多数时候,你应该只会用到 leave 钩子 onBeforeLeave(el) {}, // 在离开过渡开始时调用 // 用这个来开始离开动画 onLeave(el, done) { // 调用回调函数 done 表示过渡结束 // 如果与 CSS 结合使用,则这个回调是可选参数 done() }, // 在离开过渡完成、 // 且元素已从 DOM 中移除时调用 onAfterLeave(el) {}, // 仅在 v-show 过渡中可用 onLeaveCancelled(el) {} }}
这些钩子可以与 CSS 过渡或动画结合使用,也可以单独使用。
来自 <Transition | Vue.js>