1.生命周期函数
2.生命周期函数(Ⅱ)
3.watch监听属性
4.computed计算属性

1.生命周期函数

创建阶段

1
2
3
4
5
6
7
8
9
1.beforeCreate():表示实例完全被创建时,会执行它
/ps:在beforCreate生命周期函数执行时,data和methods中的数据均未被初始化

2.created():在created中,data与methods都已经被实例化了,

3.beforeMount(): 表示模板已经在内存中编译好了,只是未渲染到真正要展示的页面上

4.mounted():是实例创建期间最后一个生命周期函数,当执行完mounted就表示,实例已经完全创建好了,
此时,如果没有其它操作的话,这个实例就静静地躺在内存中

组件运行阶段:

1
2
3
4
1.beforeUpdate(): 表示我们的界面还没有更新,但数据肯定被更新了 
结论:运行beforeUpdate,页面上显示的数据还没有被更新,但数据已经更新了,页面与数据更新不同步

2.updated():页面都data数据已经保持同步了,都是最新的

销毁过程

1
2
3
1.beforeDestroy:Vue示例已经从运行阶段,进入到销毁阶段,实例身上的所有data,methods以及过滤器,指令都处于可用状态,未执行真正的销毁动作

2.destroyed:组件已经完全销毁了,一切data,方法,指令,过滤器均不可使用

2. 生命周期函数(二)

在理清生命周期函数之前,先看两张图

  • 初识:

  • 详解:

  • 小结一:
  1. created执行时会初始化Vue实例的数据对象data。但$el,dom树还没有加载,即改变 data() 中的数据是不会触发 change 事件的,无法进入 watch 代码部分
  2. mounted执行时,vue实例挂载完成,data.filter成功渲染,即此时改变 data 中的数据是会触发 change 事件的,也就能被 watch 到
  3. 关于create函数和watch执行顺序问题,一般在watch里面写上immediate:true,会使得执行优先级高于created
  4. watch 与 computed 的区别,最关键的是watch需要监听值的变化而改变,但是computed从一开始就可以达到和某个值关联起来(computed会忽略其它生命周期函数,从一开始就会监听某个值)

案例一:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<template>
<div>
<p> {{ firstNum }} </p>
<p> {{ secondNum }} </p>
<p> {{ thirdNum }} </p>
</div>
</template>

<script>

export default {
data() {
return {
firstNum: 0,
thirdNum: 0
}
},
created() {
// 该步骤在 data() 数据实例化之前。
// 此时改变 data() 中的数据是不会触发 change 事件的,无法进入 watch 代码部分。
this.firstNum = 1;
console.log('created: ' + this.firstNum);
},
mounted() {
// 该步骤在 data 数据实例化之后。
// 此时改变 data 中的数据是会触发 change 事件的,也就能被 watch 到。
this.firstNum = 2;
console.log('mounted: ' + this.firstNum)
},
computed: {
secondNum() {
// firstNum 从一开始就与之绑定关联
console.log('secondNum is computing: ' + this.firstNum * 100);
return this.firstNum * 100;
}
},
watch: {
firstNum(val) {
// firstNum 只有在发生改变时,才会进入该逻辑
console.log('firstNum is watched: ' + val);
this.thirdNum = val * 100
}
}
}
</script>

执行结果如何呢:

  • html显示结果:
1
2
3
4
5
2

200

200
  • console.log显示结果:
1
2
3
4
5
created: 1
secondNum is computing: 100
mounted: 2
firstNum is watched: 2
secondNum is computing: 200
  • 结果解释:

created方法是在data()数据初始化之前执行,开始执行created方法,给firstNum赋值为1,并console当前的firstNum赋值后的值

由于created方法执行后,并没有挂载$el,改变 data() 中的数据是不会触发 change 事件的,无法进入 watch 代码部分

firstNum被赋值后,由于computed从一开始就可以达到和firstNum关联起来,firstNum值改变,执行计算方法

接下来开始执行mounted方法,挂载$el,完成DOM树的创建,数据完成渲染。firstNum再次被赋值,由于此时数据已完成渲染,此时改变 data 中的数据是会触发 change 事件的,也就能被 watch 到

执行完watch完后,computed再检测有没有数据的变更

案例二:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<body>
<div id="app">
<div>
{{msg}}
</div>
<ul>
<li v-for="a in arr"></li>
</ul>
<button @click="fn">点我一下</button>
</div>
<script src="../node_modules/axios/dist/axios.js"></script>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
// 生命周期: Vue是一个构造函数,当执行执行这个函数时,相当于初始化vue实例;
// 在创建实例过程中,需要设置数据监听,编译模板,将实例挂载到DOM上,数据更新能够让DOM也更新,
// 在这个初始化,又会不同阶段默认调用一些函数执行,这些函数就是生命周期的钩子函数;

// 生命周期钩子函数,让够让咱们在初始化实例时,添加自己的代码;
//生命周期的钩子函数中的this,会默认指向vue的实例
// beforeCreate created
// beforeMount mounted
// beforeUpdate updated
// beforeDestroy destroyed

let vm = new Vue({
data: {
msg: "hello",
arr: [1, 2, 3, 4]
},
// 1. 在这个钩子函数执行之前初始化事件以及生命周期
beforeCreate() {
// 1. 在这个钩子函数中,不能获取data中的数据
// console.log(this.msg);
// 2. 这个函数不能操作DOM;
// console.log(document.getElementsByTagName("li"))
},
// 给Vue的实例注入数据,进行数据监听
created() {
// 在created发送请求
// 1. 可以获取到data中的数据
// 2. 不能操作DOM的
// console.log(this.msg);
// console.log(document.getElementsByTagName("li"))

axios.get("./carts.json").then(data => {
// 异步的;
this.arr = data.data;
console.log(2);

})
},
methods: {
fn() {
this.msg = "world"
}
},
// 执行之前,判断是否有el,template;编译
beforeMount() {
// console.log(document.getElementsByTagName("li"))
},
// 挂载完毕
mounted() {
// debugger
// 挂载: 把VUE实例生成的虚拟的DOM转成真实的DOM,放在了页面中,这就是挂载;
// 编译出的DOM把原有的DOM替换完毕;
// 可以获取最终的DOM元素
// let d = {type:"div",a:"1",chidlren:[{type:"span",children:[]}]}
console.log(document.getElementsByTagName("li"));
//console.log("mounted","初始化");
},
// 当数据更新时,会调用beforeUpdate 和updated钩子函数;上面四个不再运行
beforeUpdate() {
console.log("beforeUpdate", "更新之前");
console.log(this.msg)
// 更新数据之前执行
},
updated() {
console.log("beforeUpdate", "更新之后");
// 数据更新,虚拟的DOM更新,然后更新真实的DOM;最后触发这个函数
},
// 销毁之前
beforeDestroy() {
// 销毁之前
// 清除定时器
console.log("beforeDestroy");

},
// 销毁之后
destroyed() {
console.log("destroyed");
// 销毁子组件,销毁观察者,事件监听者
// 元素的事件还在,但是更改数据不会再让视图进行更新了;
}
}).$mount("#app");
// vm.$destroy();
// console.log(vm);
// 在项目中,你遇到过什么问题,怎么解决的?
// 准备
</script>
</body>
</html>

3.watch监听属性

Watch:可以监听data属性域中的数据变化,主要有handler方法,immediate属性,deep属性

  • handler方法就是你watch中需要具体执行的方法
  • immediate为true时则立即触发回调函数;如果为false,则和上面的例子一样,不会立即执行回调
  • deep顾名思义就是深入监听,也就是在对象中层层遍历,并在监听对象上的每一个属性上都添加监听,固然也会损耗性能
1
2
3
4
5
6
7
8
9
watch: {
orgBarChartData: { // 监听的目标属性
handler(newVal,oldVal){
this.renderOrgBarChart(); //重设图表,这两个都是动作体
this.orgBarChart.resize(); //重新设置图表高宽
},
deep: true // deep:true
},
}

4.computed计算属性

computed和methods虽然都可以实现对数据的计算,但两者有一定的区别:

  • methods:使用methods方法可以接受外部传参,使用更加灵活
  • computed:
    • 计算属性computed的亮点在于:它能够依赖缓存,当计算属性所依赖的数据发生改变时,才会重新触发计算属性方法执行。所以对于较复杂或消耗效率的计算,一定要采用计算属性。
    • 计算属性computed里面也可以写函数,并且调用函数时使用的mustache语法不用加括号
    • computed里虽然存放的是函数,但在调用时,computed里的东西是一个属性,所以我们在调用时不能使用() ,因为()表示是在调用函数,而不是调用属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div id="app">
<!--这里的mustache语法调用计算属性时没有声明括号-->
<p>{{fullName}}</p>
</div>
<script >
const vm = new Vue({
el: '#app',
data:{
firstName:"985",
lastName:"Miss"
},
computed:{
fullname () {
return this.lastName+this.firstName;
}
},
methods:{}
})
</script>

参考文章


 评论

联系我 | Contact with me

Copyright © 2019-2020 谁知你知我,我知你知深。此恨经年深,比情度日久

博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议