使用vue框架,需要在合适的时机做合适的事情,了解了vue对象的生命周期和钩子函数,才能知道,哪些事情应该咋哪个函数里做。
一、vue的生命周期的理解
- 生命周期
用人举例说明:
生命周期就是一个人的一生,此处我需要说的没有人情一点(哈哈)。
从人的出生,到成长,到工作,到死亡,就是人的一生,也叫一个人的生命周期。
2. 对象的生命周期
在程序开发中,是要使用对象的。那么,对象的生命周期就是:从对象的创建,到使用对象,到对象的消亡就是对象的生命周期。
用人和对象进行类比(此处没有人性):
人 | 程序中的对象 |
人出生 | New对象 |
人工作(ps:要人的目的就是为了工作,如果一个人不工作,不为国家做贡献,那就不是合格的人,活着没有意义) | 使用对象的方法和属性(ps:new的对象的目的就是为了用它,用对象主要就是使用对象的方法和属性) |
人死亡(ps:人没有用了,那就“去死吧”) | 对象使用完就该消亡了(过河拆桥,不用了,那就不要了。) |
3. Vue的生命周期
Vue实例,vue组件实例就是vue对象,也是对象。所以,vue的生命周期和对象的生命周期是同样的道理
二、vue生命周期经历的阶段
生命周期是有不同的阶段的,就像人一样,有幼儿期,童年期,少年期,青年期,中年期,老年期。每个阶段应该做不同的事情,但是每个人做的事情又不尽相同。
Vue对象的生命周期也分不同的阶段,不同的阶段也可以做不同的事情,但是不同的vue(组件)对象在不同的阶段做的事情也不尽相同,所以,每个vue组件的代码不相同。
Vue生命周期经历哪些阶段:
- 总体来说:初始化、运行中、销毁
- 详细来说:开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、销毁等一系列过程
三、生命周期经历的阶段和钩子函数
- 实例化vue(组件)对象:new Vue()
- 初始化事件和生命周期 init events 和 init cycle
- BeforeCreated函数:
在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
即此时vue(组件)对象被创建了,但是vue对象的属性还没有绑定,如data属性,computed属性还没有绑定,即没有值。
此时还没有数据和真实DOM。
即:属性还没有赋值,也没有动态创建template属性对应的HTML元素(二阶段的createUI函数还没有执行)
4. 挂载数据(属性赋值)
包括 属性和computed的运算,
5. Created函数:
vue对象的属性有值了,但是DOM还没有生成,$el属性还不存在。
此时有数据了,但是还没有真实的DOM
即:data,computed都执行了。属性已经赋值,但没有动态创建template属性对应的HTML元素,所以,此时如果更改数据不会触发updated函数
如果:数据的初始值就来自于后端,可以发送ajax,或者fetch请求获取数据,但是,此时不会触发updated函数
6. 检查
1)检查是否有el属性
检查vue配置,即new Vue{}里面的el项是否存在,有就继续检查template项。没有则等到手动绑定调用vm.$mount()
完成了全局变量$el的绑定。
2)检查是否有template属性
检查配置中的template项,如果没有template进行填充被绑定区域,则被绑定区域的el对象的outerHTML(即整个#app DOM对象,包括<div id=”app” >和</div>标签)都作为被填充对象替换掉填充区域
即:如果vue对象中有 template属性,那么,template后面的HTML会替换$el对应的内容。如果有render属性,那么render就会替换template。
即:优先关系时: render--à template --àel
7 beforeMonute函数:
模板编译(template)、数据挂载之前执行的钩子函数
此时 this.$el有值,但是数据还没有挂载到页面上。即此时页面中的{{}}还没有被替换
8. 用vue对象的数据(属性)替换模板中的内容
9. Monuted函数:
模板编译完成,数据挂载完毕
即:此时已经把数据依据挂载到了页面上,所以,页面上能够看到正确的数据了。
一般来说,我们在此处发送异步请求(ajax,fetch,axios等),获取服务器上的数据,显示在DOM里。
10. beforeUpdate函数:
组件更新之前执行的函数
数据更新了,但是,vue(组件)对象对应的dom中的内部(innerHTML)没有变,所以叫作组件更新前
11. updated函数:
组件更新之后执行的函数
vue(组件)对象对应的dom中的内部(innerHTML)改变了,所以,叫作组件更新之后
12. activated函数:keep-alive组件激活时调用
13. deactivated函数:keep-alive组件停用时调用
14. beforeDestroy:vue(组件)对象销毁之前
15. destroyed:vue组件销毁后
四、测试代码
-
<!DOCTYPE html>
-
<html lang="en">
-
<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>vue生命周期学习
</title>
-
</head>
-
<body>
-
<div id="app">
-
<h1>{{message}}
</h1>
-
<h1>count:{{count}}
</h1>
-
</div>
-
<input id="btn01" type="button" value="测试" />
-
</body>
-
<script type="text/javascript" src="js/vue.min.js" >
</script>
-
<script>
-
var vm =
new Vue({
-
el:
'#app',
-
data: {
-
message:
'Vue的生命周期',
-
age:
2
-
},
-
computed:{
-
count:
function(){
-
return
this.age+
1;
-
}
-
},
-
// template:"<p>vue对象中的template的内容</p>",
-
// render: function(createElement) {
-
// return createElement('h1', 'this is createElement')
-
// },
-
beforeCreate:
function() {
-
console.group(
'------beforeCreate创建前状态------');
-
console.log(
"%c%s",
"color:red" ,
"el : " +
this.$el);
//undefined
-
console.log(
"%c%s",
"color:red",
"data : " +
this.$data);
//undefined
-
console.log(
"%c%s",
"color:red",
"count : " +
this.count);
//undefined
-
console.log(
"%c%s",
"color:red",
"message: " +
this.message)
-
},
-
created:
function() {
-
console.group(
'------created创建完毕状态------');
-
console.log(
"%c%s",
"color:red",
"el : " +
this.$el);
//undefined
-
console.log(
"%c%s",
"color:red",
"data : " +
this.$data);
//已被初始化
-
console.log(
"%c%s",
"color:red",
"count : " +
this.count);
//undefined
-
console.log(
"%c%s",
"color:red",
"message: " +
this.message);
//已被初始化
-
},
-
//完成了el的绑定
-
beforeMount:
function() {
-
console.group(
'------beforeMount挂载前状态------');
-
console.log(
"%c%s",
"color:red",
"el : " + (
this.$el));
//已被初始化
-
console.log(
this.$el.innerHTML);
-
console.log(
"%c%s",
"color:red",
"data : " +
this.$data);
//已被初始化
-
console.log(
"%c%s",
"color:red",
"message: " +
this.message);
//已被初始化
-
},
-
mounted:
function() {
-
console.group(
'------mounted 挂载结束状态------');
-
console.log(
"%c%s",
"color:red",
"el : " +
this.$el);
//已被初始化
-
console.log(
this.$el);
-
console.log(
this.$el.innerHTML);
-
console.log(
"%c%s",
"color:red",
"data : " +
this.$data);
//已被初始化
-
console.log(
"%c%s",
"color:red",
"message: " +
this.message);
//已被初始化
-
},
-
beforeUpdate:
function () {
-
console.group(
'beforeUpdate 更新前状态===============》');
-
console.log(
"%c%s",
"color:red",
"el : " +
this.$el);
-
console.log(
this.$el.innerHTML);
-
console.log(
"%c%s",
"color:red",
"data : " +
this.$data.message);
-
console.log(
"%c%s",
"color:red",
"message: " +
this.message);
-
}
-
,
-
updated:
function () {
-
console.group(
'updated 更新完成状态===============》');
-
console.log(
"%c%s",
"color:red",
"el : " +
this.$el);
-
console.log(
this.$el.innerHTML);
-
console.log(
"%c%s",
"color:red",
"data : " +
this.$data);
-
console.log(
"%c%s",
"color:red",
"message: " +
this.message);
-
},
-
// beforeDestroy: function () {
-
// console.group('beforeDestroy 销毁前状态===============》');
-
// console.log("%c%s", "color:red","el : " + this.$el);
-
// console.log(this.$el);
-
// console.log("%c%s", "color:red","data : " + this.$data);
-
// console.log("%c%s", "color:red","message: " + this.message);
-
// },
-
// destroyed: function () {
-
// console.group('destroyed 销毁完成状态===============》');
-
// console.log("%c%s", "color:red","el : " + this.$el);
-
// console.log(this.$el);
-
// console.log("%c%s", "color:red","data : " + this.$data);
-
// console.log("%c%s", "color:red","message: " + this.message)
-
// }
-
});
-
-
document.getElementById(
"btn01").onclick =
function(){
-
vm.message=
"改了";
-
}
-
五、模拟vue的构造函数(部分代码)
myVue.js
-
class MyVue{
-
constructor(obj){
-
//默认值
-
let defaultObj={
-
data:
null,
-
computed:
null,
-
watch:
null,
-
beforeCreate:
function(){
-
-
},
-
created:
function(){
-
-
},
-
beforeMount:
function(){
-
-
},
-
mounted:
function(){
-
-
}
-
}
-
for(
let key
in defaultObj){
-
obj[key]?
this[key]=obj[key]:
this[key]=defaultObj[key];
-
}
-
-
//对象创建完毕已经有this了。
-
this.beforeCreate();
-
//挂载数据:
-
//1)、把传入的data属性的值赋给this
-
if(obj.data){
-
for(
let key
in
this.data){
-
this[key] = obj.data[key];
-
}
-
this.$data = obj.data;
//设置全局变量
-
}
-
//2)、计算属性
-
if(obj.computed){
-
for(
let key
in obj.computed){
-
this[key] = obj.computed[key].call(
this);
-
}
-
}
-
//created函数
-
this.created();
-
//检查是否有el属性
-
if(obj.el){
-
this.el = $(obj.el);
-
this.$el = $(obj.el);
//设置全局变量
-
}
-
//检查是否有template属性
-
if(
this.template){
-
//this.template = obj.template;
-
// 动态创建template 里所有的html元素
-
}
-
//beforeMonute
-
this.beforeMount();
-
//用vue对象的数据(属性)替换模板中的内容
-
//1)、替换data中的数据
-
let html =
this.el.innerHTML;
-
for(
let key
in
this.data){
-
//用属性值替换,属性名(页面上用双花括号包起来的)
-
html=html.replace(
new
RegExp(
"{{"+key+
"}}",
"g"),
this[key]);
-
}
-
//2)、替换computed中的数据
-
for(
let key
in
this.computed){
-
//用属性值替换,属性名(页面上用双花括号包起来的)
-
html=html.replace(
new
RegExp(
"{{"+key+
"}}",
"g"),
this[key]);
-
}
-
this.el.innerHTML = html;
-
-
//mounted函数:
-
this.mounted();
-
}
-
-
addWatch(){
-
-
}
-
-
//数据双向绑定
-
-
//
-
}
-
-
function $(str){
//#box .cls p
-
if(str.charAt(
0)==
"#"){
-
return
document.getElementById(str.substring(
1));
-
}
else
if(str.charAt(
0)==
"."){
-
return
document.getElementsByClassName(str.substring(
1));
-
}
else{
-
return
document.getElementsByTagName(str);
-
}
-
}
html代码:
<body>
<div id="app">
<h1>{{message}}</h1>
<h1>count:{{count}}</h1>
</div>
</body>
<script type="text/javascript" src="js/myvue.js" ></script>
<script>
var vm = new MyVue({
el: '#app',
data: {
message: 'Vue的生命周期',
age:1
},
computed:{
count:function(){
return this.age+1;
}
},
beforeCreate: function() {
console.group('------beforeCreate创建前状态------');
console.log("%c%s", "color:red" , "el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //undefined
console.log("%c%s", "color:red","message: " + this.message)
},
created: function() {
console.group('------created创建完毕状态------');
console.log("%c%s", "color:red","el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
//完成了el的绑定
beforeMount: function() {
console.group('------beforeMount挂载前状态------');
console.log("%c%s", "color:red","el : " + (this.$el)); //已被初始化
console.log(this.$el);
console.log(this.$el.innerHTML);
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
},
mounted: function() {
console.group('------mounted 挂载结束状态------');
console.log("%c%s", "color:red","el : " + this.$el); //已被初始化
console.log(this.$el);
console.log(this.$el.innerHTML);
console.log("%c%s", "color:red","data : " + this.$data); //已被初始化
console.log("%c%s", "color:red","message: " + this.message); //已被初始化
}
})