生命周期简介
每个Vue
实例在被创建时都要经过一系列的初始化过程,例如:需要设置数据的监听,编译模板,将实例挂载到DOM
上,并且在数据变化时更新DOM
等,这些过程统称为Vue
实例的生命周期
。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
其实Vue
实例的生命周期,主要分为三个阶段,每个阶段都会执行不同的钩子函数,分别为
-
挂载(初始化相关属性,例如
watch
属性,method
属性)-
beforeCreate
-
created
-
beforeMount
-
mounted
-
-
更新(元素或组件的变更操作)
-
beforeUpdate
-
updated
-
-
销毁(销毁相关属性)
-
beforeDestroy
-
destroyed
下面请看一张Vue生命进程图(图片可能有点大)
钩子函数:
第一步:
beforeCreate
: Vue
实例初始化之后,以及事件初始化,以及组件的父子关系确定后执行该钩子函数,一般在开发中很少使用
created
: 在调用该方法之前,初始化会被使用到的状态,状态包括props
,methods
,data
,computed
,watch
.
而且会实现对data
中属性的监听,也就是在created
的时候数据已经和data
属性进行了绑定。(放在data
中的属性当值发生改变的时候,视图也会改变)。同时也会对传递到组件中的数据进行校验。
所以在执行created
的时候,所有的状态都初始化完成,我们也完全可以在该阶段发送异步的ajax
请求,获取数据。
但是,在created
方法中,是无法获取到对应的的$el
选项,也就是无法获取Dom
请看如下代码:
created() { console.log("created"); console.log("el===", this.$el);// undefined console.log("data==", this.$data);// 可以获取数据 console.log("foo==", this.foo);//可以获取数据 },
第二步:
created
方法执行完毕后,下面会判断对象中有没有el
选项。如果有,继续执行下面的流程,也就是判断是否有template
选项,
如果没有el
选项,则停止整个生命周期的流程,直到执行了vm.$mount(el)
下面请看代码:
<script> const vm = new Vue({ // el: "#app", //去掉了el选项 data: { foo: "fooData", }, methods: { beforeCreate() { console.log("beforCreate"); }, created() { console.log("created"); console.log("el===", this.$el); console.log("data==", this.$data); console.log("foo==", this.foo); }, }); </script>
在上面的代码中,我们将el
选项去掉了,运行上面的代码后,我们发现执行完created
方法后,整个流程就停止了。
现在,我们不添加el
选项,但是手动执行vm.$mount(el)
,也能够使暂停的生命周期进行下去。如下面代码
<script> const vm = new Vue({ // el: "#app",//去掉了el选项 data: { foo: "fooData", }, methods: { beforeCreate() { console.log("beforCreate"); }, created() { console.log("created"); console.log("el===", this.$el); console.log("data==", this.$data); console.log("foo==", this.foo); }, }); vm.$mount("#app");//添加了$mount方法 </script>
下面请看图
我们继续向下看,就是判断在对象中是否有template
选项。
第一:如果Vue
实例对象中有template
参数选项,则将其作为模板编译成render
函数,来完成渲染。
第二:如果没有template
参数选项,则将外部的HTML作
为模板编译(template
),也就是说,template
参数选项的优先级要比外部的HTML
高
第三:如果第一条,第二条件都不具备,则报错
Vue
需要通过el
的“选择器”找到对应的template
.也就是说,Vue
首先通过el
参数去查找对应的template
.如果没有找到template
参数,则到外部HTML
中查找,找到后将模板编译成render
函数(Vue
的编译实际上就是指Vue
把模板编译成render
函数的过程)。还有一点需要注意(template
参数的优先级比外部HTML
的优先级要高。)如果同时有template模板与外部的html,
则会优先渲染template里面的数据
第三步:
接下来会触发`beforeMount`这个钩子函数:如下图
在执行该钩子函数的时候,虚拟`DOM`已经创建完成,马上就要渲染了,在这里可以更改`data`中的数据,不会触发`updated`, 其实在`created`中也是可以更改数据,也不会触发`updated`函数
测试代码如下:
beforeMount() { console.log("beforeMount"); console.log("beforeMount el===", this.$el); console.log("data==", this.$data); //this.foo = "abc"; //修改数据 console.log("foo==", this.foo); },
通过上面的代码,我们可以获取`el`中的内容,同时也可以修改数据。
但是,这里需要注意的输入的`el`中的内容,`{{foo}}`还没有被真正的数据替换掉。而且对应的内容还没有挂载到页面上。
下面执行了`Create VM.$el and replace "el" with it`
经过这一步后,在模板中所写的`{{foo}}`会被具体的数据所替换掉。
所以下面执行`mounted`的时候,可以看到真实的数据。同时整个组件内容已经挂载到页面中了,数据以及真实`DOM`都已经处理好了,可以在这里操作真实`DOM`了,也就是在`mounted`的时候,页面已经被渲染完毕了,在这个钩子函数中,我们可以去发送`ajax`请求。
第四步:如下图
当整个组件挂在完成后,有可能会进行数据的修改,当Vue
发现data
中的数据发生了变化,会触发对应组件的重新渲染,先后调用了beforeUpdate
和updated
钩子函数。
在updated
之前beoreUpdate
之后有一个非常重要的操作就是虚拟DOM
会重新构建,也就是新构建的虚拟DOM
与上一次的虚拟DOM
树利用diff
算法进行对比之后重新渲染。
而到了updated
这个方法,就表示数据已经更新完成,dom
也重新render
完成。
第五步:
下面如果我们调用了vm.$destroy
方法后,就会销毁所有的资源。
首先会执行beforeDestroy
这个钩子函数,这个钩子函数在实例销毁前调用,在这一步,实例仍然可用。
在该方法中,可以做一些清理的工作,例如:清除定时器等。
但是执行到destroyed
钩子函数的时候,Vue
实例已经被销毁,所有的事件监听器会被移除,所有的子实例也会被销毁
最后来个总结:
beforeCreate( )// 该钩子函数执行时,组件实例还未创建. created()//组件初始化完毕,各种数据可以使用,可以使用ajax发送异步请求获取数据 beforeMounted()// 未执行渲染,更新,虚拟DOM完成,真实DOM未创建 mounted()// 初始化阶段结束,真实DOM已经创建,可以发送异步请求获取数据,也可以访问dom元素 beforeUpdate()//更新前,可用于获取更新前各种状态数据 updated()//更新后执行该钩子函数,所有的状态数据是最新的。 beforeDestroy() // 销毁前执行,可以用于一些定时器的清除。 destroyed()//组件已经销毁,事件监听器被移除,所有的子实例也会被销毁。
以上为vue生命周期内容,如果有哪里写错了,欢迎各位大佬指正,谢谢大家!