vue生命周期与钩子函数
文章目录
组件的创建到销毁的一系列过程叫做组件的生命周期。
先来一张Vue官网的图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HRGwMJpP-1585113315704)(lifecycle-1585098160285.png)]
生命周期大致分为三个阶段:初始化、运行中、销毁
初始化阶段
beforeCreate
created
beforeMount
mounted
beforeCreate
组件通过new Vue() 创建出来之后会初始化事件和生命周期后 立即执行
数据还没有挂载到,无法访问到数据和真实的dom
一般不做操作
beforeCreate(){
//undefined null
console.log(this.msg,document.getElementById("title"))
},
created
数据已被挂载,真实 dom 还没被渲染出来,执行该函数
可以访问到数据,无法访问页面中的真实 dom 元素
在这里同步更改数据 不会触发 运行中的 updated 函数
一般可以在这里做初始数据的获取。 做异步ajax,绑定初始化事件
created(){
// this.msg = 222222222222222 可以更改数据,不触发updated函数
//1 null
console.log(this.msg,document.getElementById("title"))
},
beforeMount
找实例或者组件对应的模板,编译模板为虚拟dom放入到 render 函数中准备渲染,然后执行该函数
用法大致与 created 一样,可以做ajax与初始化事件的绑定操作
beforeMount(){
//1 null
console.log(this.msg,document.getElementById("title"))
},
mounted
开始执行render函数渲染页面,渲染出真实dom了,然后执行该函数
可以访问到数据 和 页面中的真实 dom 元素
可以用来做一些实例化的相关操作 ===> 拖拽
render(){
console.log("render.....")
}
执行以上函数后可发现,页面元素不被渲染出来,说明该函数把组件内部的 render 函数覆盖了,证明渲染页面是通过 render 函数执行
mounted(){
//1 <h1 id="title"> hello </h1>
console.log(this.msg,document.getElementById("title"))
},
运行阶段
beforeUpdate
updated
beforeUpdate
dom 挂载完毕了,然后再去当数据 发生变化 的时候,立即执行该函数
该函数执行后,会进行重新构建虚拟 dom,通过 diff 算法与上一次虚拟 dom 进行比较后重新渲染
一般不做什么事儿
updated
数据更新完毕,dom也重新 render 完成,执行该函数
可以操作更新后的dom
销毁阶段
beforeDestroy
destroyed
beforeDestroy
调用 $destroy 方法后,立即执行该函数
一般做一些善后工作,例如清除计时器、清除非指令绑定的事件等等
destroyed
销毁完毕,只剩下dom空壳,没有任何事件的绑定与数据的双向绑定,所有的子实例也都被销毁
做善后工作也可以
小案例
为了加深印象,可以结合生命周期,完成一个轮播图的小案例
本案例引用 vue框架、swiper插件、vue-resource插件实现
引入需要的插件
<link rel="stylesheet" href="../base/swiper.min.css" />
<script src="../base/swiper.min.js"></script>
<script src="../base/vue.js"></script>
<script src="https://cdn.bootcss.com/vue-resource/1.5.0/vue-resource.min.js"></script>
页面标签如下:
<div id="app">
<my-banner></my-banner>
</div>
<template id="my-banner">
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="banner in banners" :key="banner.id">
<img width="100%" :src="banner.image" alt="" />
</div>
</div>
</div>
js代码如下:
Vue.component("my-banner", {
template: "#my-banner",
data() {
return {
banners: []
};
},
created() {
//发送请求获取数据
this.$http.get("./banners.json").then(res => {
console.log(res.data.bannerList);
this.banners = res.data.bannerList;
this.mySwiper = new Swiper(".swiper-container", {
//实例化swiper对象
loop: true, // 循环模式选项
autoplay: {
//自动轮播
delay: 1000
}
});
});
}
});
new Vue({
el: "#app"
});
本以为以上代码就可以了,异步获取到数据再初始化swiper对象,但是结果却出问题了,划不动轮播图,也没有自动轮播
原因是什么呢?
结合之前讲过的生命周期钩子函数,豁然开朗,created函数只是挂载数据的,真实的 dom 并没有被渲染出来,所以自然就初始化失败了
怎么解决:
那么将初始化函数放到 mounted 函数里面可以吗?答案是否定的,因为发送请求是异步操作,所以一开始数据为空的时候直接就执行到 mounted 函数,直接开始初始化,之然会失败
所以我们应该将初始化函数放到 updated 函数中,
这样,当请求数据回来的时候,会改变原数据,修改完成,并且与上一次虚拟 dom 进行对比,更新渲染到视图完成后,就会触发 updated 函数,
这时,再进行 swiper 的实例化/初始化就没问题了。
所以,js代码修改为:
Vue.component("my-banner", {
template: "#my-banner",
data() {
return {
banners: []
};
},
created() {
//发送请求获取数据
this.$http.get("./banners.json").then(res => {
console.log(res.data.bannerList);
this.banners = res.data.bannerList;
});
},
updated() {
this.mySwiper = new Swiper(".swiper-container", {
//实例化swiper对象
loop: true, // 循环模式选项
autoplay: {
//自动轮播
delay: 1000
}
});
}
});
new Vue({
el: "#app"
});
这样,就可以简单的实现一个轮播图实例了~
以上就是本人的学习总结,如有不对,欢迎指出~