一、理解
生命周期:从一个组件创建、数据初始化、编译模板、挂载Dom、渲染、更新、销毁。历经如下步骤
beforeCreate->watch->created->computed->beforeMount->mounted->beforeUpdate->updated->beforeDestroy->destroyed
二、生命周期
1、new Vue()
实例化一个Vue实例。生命周期的钩子函数中的this,会默认指向vue的实例。
2、beforeCreate(){}
数据观测和事件配置之前被调用,此时组件的选项对象还未创建,el 和 data 并未初始化,因此无法访问methods, data, computed等上的方法和数据
3、watch:{}
后续详细讲解
4、created(){}
完成了data 数据的初始化,el没有。以及能获取到methods下的方法了, 所以在这里可以开始调用方法进行请求。
5、computed:{}
后续详细讲解
6、beforeMount(){}
也就是说实际从created到beforeMount之间,最主要的工作就是将模板或者el转换成render函数。并且我们可以看出一点,就是你不管是用el,还是用template, 或者是用我们最常用的.vue文件(如果是.vue文件,他其实是会先编译成为template),最终他都是会被转换为render函数的。
所以挂在开始之前被调用,相关的render函数首次被调用(虚拟DOM),实例已完成以下的配置: 编译模板,把data里面的数据和模板生成html,完成了el和data 初始化,注意此时还没有挂在html到页面上。
7、mounted(){}
数据和DOM都完成挂载(即模板完成了渲染),在上一个周期占位的数据把值给渲染进去。可以在这边请求,不过created请求会更好一些。这个周期适合执行初始化需要操作DOM的方法
8、beforeUpdate(){}
实现原理:当调用时候,我们又重新生成一个新的虚拟dom(Vnode),然后拿这个Vnode和原来的Vnode去做一个diff算,从而更新render函数中的最新数据,再讲更新后的render函数渲染成真实的dom。也就完成了我们的数据更新
只要是页面数据改变了都会触发,数据更新之前,页面数据还是原来的数据,当你请求赋值一个数据的时候会执行这个周期,如果没有数据改变不执行。
9、updated(){}
只要是页面数据改变了都会触发,数据更新完毕,页面的数据是更新完成的。beforeUpdate和updated要谨慎使用,因为页面更新数据的时候都会触发,在这里操作数据很影响性能和容易死循环。
10、beforeDestroy(){}
这个周期是在组件销毁之前执行,在我项目开发中,觉得这个其实有点类似路由钩子beforeRouterLeave,都是在路由离开的时候执行,只不过beforeDestroy无法阻止路由跳转,但是可以做一些路由离开的时候操作,因为这个周期里面还可以使用data和method。比如一个倒计时组件,如果在路由跳转的时候没有清除,这个定时器还是在的,这时候就可以在这个里面清除计时器。
11、destroyed(){}
销毁完成后
注意:
mouted和updated的执行,并不会等待所有子组件都被挂载完成后再执行,所以如果你希望所有视图都更新完毕后再做些什么事情,那么你最好在mouted或者updated中加一个$nextTick(),然后把要做的事情放在$netTick()中去做
三、computed和watch
1、watch:数据变化时执行异步或开销较大的操作,可以随时修改状态的变化。主要用于监控vue实例的变化,它监控的变量当然必须在data里面声明才可以,它可以监控一个变量,也可以是一个对象。其类似于监听机制+事件机制
2、computed:当页面中有某些数据依赖其他数据进行变动的时候,可以使用计算属性,是基于data中数据进行处理的,data数据变化,他也跟着变化。当data中数据没有发生改变时,我们调用computed中函数n次,只会进行缓存(执行一次)
watch和computed区别:
1.watch擅长处理的场景:一个数据影响多个数据;不支持缓存,数据变,直接会触发相应的操作;watch支持异步,或者在高性能消耗操作上执行。
2.computed擅长处理的场景:一个数据受多个数据影响;支持缓存,只有依赖数据发生改变,才会重新进行计算;不支持异步;
1、watch的普通使用
<template>
<div id="login">
<div class="wrapper">
<template>
<div class="content">
<h3>验证watch使用场景</h3>
密码: <input v-model="nameValue" type="text" /> {{ tip }}
</div>
</template>
</div>
</div>
</template>
<script>
export default {
data() {
return {
nameValue: "",
tip: "",
};
},
watch: {
// 数据变化时执行异步或开销较大的操作
nameValue(value) { // 普通使用
this.checkName(value);
},
},
methods: {
checkName(value) {
const that = this;
if (value === "admin") {
that.tip = "12345";
} else {
that.tip = "abc123";
}
},
},
};
</script>
<style>
@import "../assets/css/my.css";
</style>
2、watch高级用法
备注:上面的watch方法是当改变值时候,才会触发监听事件,但是我们刚进入页面时候,就触发监听事件,就要用handler()方法
2.1 handler()
当页面刚进入时,自动绑定watch事件,不需要进行触发
watch: {// 页面加载时,就自动触发此事件
nameValue:{
handler(new){
this.checkName(value);
this.tip = "正在验证......";
}
}
}
2.2 immediate属性:布尔值
immediate:true:首次加载、刷新、数据改变都会执行,缺点监听不到对象属性中发生改变。
immediate:false:只有发生改变才监听
nameValue: {
handler(value) {
this.checkName(value);
this.tip = "正在验证......";
},
immediate: true,
},
2.3 deep:true;
是开启深层次的监听,即所有属性都加上监听器,如果其中一个发生改变了就执行handler函数。
nameValue: {
handler(value) {
this.checkName(value);
this.tip = "正在验证......";
},
immediate: true,
deep:true
},
如果想要监听getParm里面某个值的变化,比如监听getParm对象的keyword的值,可以这么写(监听对象里的某个属性要加' '):
watch:{
'getParam.keyWord':{
handler(newValue,oldValue){
//getParam.keyWord改变,执行的函数
...
},
deep:true
}
}
3、computed
在computed中,可以定义一些 属性,这些属性,叫做 【计算属性】, 计算属性的本质,就是一个方法,只不过,我们在使用这些计算属性的时候,是把它们的名称直接当作属性来使用的;并不会把计算属性当作方法去调用;
注意1、计算属性,在引用的时候,一定不要加 () 去调用,直接把它当作普通属性去使用就好了;
2、只要计算属性,这个function内部,所用到的任何data中的数据发送了变化,就会立即重新计算这个计算属性的值;
3、计算属性的求值结果,会被缓存起来,方便下次直接使用; 如果计算属性方法中,所以来的任何数据,都没有发生过变化,则不会重新对计算属性求值;
<template>
<div id="login">
<div class="wrapper">
<template>
<div class="content">
<h3>验证computed使用场景</h3>
用户名:<span>{{ fullName }}</span>
</div>
</template>
</div>
</div>
</template>
<script>
export default {
data() {
return {
firstName: "李",
lastName: "四",
};
},
computed: {
fullName() {
return this.firstName + " " + this.lastName;
},
},
};
</script>
<style>
@import "../assets/css/my.css";
</style>