对于刚接触vue一两个月、才仅仅独立作过一两个vue项目的小白来讲,之前一直自我感受本身知道vue的生命周期,html
直到前两天去面试,面试官让我说一下vue的生命周期。。。vue
其实个人心中是有那张图的,可是由于学习、分析的年代久远,心中有图殊不知道怎么表述,成了个能发声的哑吧,react
最后也就只能按顺序说出了那几个钩子函数,真是憋足了气!面试
直到今天一气呵成二刷生命周期,我才恍然大悟,原来我以前的理解中,潜意识里一直是把那几个钩子函数当作了vue的生命周期!ajax
简直了,想一想那天,面试官确定在内心把我鄙视死了吧!编程
好了不扯了,直接说我今天看完后,自我感受还很好的新的理解吧。api
也许往后再深刻接触后,会发现今天的理解也很浅显,可是至少今天比我前天好多了哈哈。app
生命周期:就是从一个组件或者实例开始被初始化、建立开始到这个实例被销毁或者结束的一个过程。dom
这个过程好比官网表述的:在过程当中须要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等ide
同时,在这个过程当中vue给咱们提供了不少的方法,也就是所说的生命周期钩子函数。
在实例生命周期的不一样阶段借助这些钩子函数,“用户在不一样阶段添加本身的代码”
由此:真正的生命周期是一个流程,而不是单单那几个钩子函数,钩子函数只是用来在流程的不一样阶段帮助咱们作更多的事情。
在我粗浅的理解下,我暂时把vue的生命周期统分红五大区块(我的的划分)
1、建立(初始化)
2、查找与处理(找到组件并渲染)
3、挂载(插入)
4、更新(从新渲染并插入)
5、销毁(卸载全部)
其中每一大块又分几个小的步骤,可是大致规律又是一模一样:
好像都是废话哈哈,但我真的对这一点的感觉很深入。
接下来一个一个来
就像咱们人从生下来到死这么一个过程,要有这个流程,先得开始:
1、建立部分
new Vue( 这句代码,初始化一个vue实例,开始建立一个vue对象
生命周期开始,init event初始化事件,为当前实例作基础配置;
建立以前,这里提供一个钩子函数,beforeCreate 开始建立钩子,
这个时候还啥也没作呢,页面一片空白,能够在页面中先展现一个loading组件,给用户一个友好体验;
建立中,init injections(初始化注册) & reactivity 建立过程当中,data属性被成功绑定,dom未生成;
建立以后,这里提供一个钩子函数,created 建立完毕钩子,
这个时候vue对象实例化完毕,dom树依旧未生成,页面仍是一片空白,
可是,实例已完成如下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。
能够在这里ajax获取数据赋给data属性了,以便往后使用;
2、查找部分
也就是new Vue()括号里边的参数开始被执行解析的过程:
new Vue({ el: '#app', router, store, template: '<App/>', components: { App } })
或
new Vue({ render (h) { return h('div', this.hi) } })
查找el属性的对应内容,el对应的DOM 元素做为 Vue 实例的挂载目标
若是值能够被找到,那么实例将当即进入编译过程
若是找不到,就去查是否在括号后边挂载了$.mount()并有内容,用于手动开启编译
以上官网解说:“若是在实例化时存在el这个选项,实例将当即进入编译过程,不然,须要显式调用 vm.$mount()
手动开启编译。”
官网:https://cn.vuejs.org/v2/api/#%E9%80%89%E9%A1%B9-DOM
若是都没找到,生命周期结束;
若是顺利的都找到了,就继续往下查找{}内的下一个属性template
若是template对应的值当中有组件或者有html内容,那么也算查找成功,
若是为空,继续查找render属性值是否为空
紧接着,若是{}选项中存在渲染函数render,
那么template将被忽略,由于render渲染函数是字符串模板的代替方案,
render可让你发挥 JavaScript 最大的编程能力,而不用写template的静态模板
若是没有或为空,template字符串模板将会替换挂载的元素,即el的属性值
挂载元素el的内容都将被忽略,除非模板template的内容有分发插槽。
若是template和render都不存在,则生命周期结束。
查找阶段汇总:
Vue 选项中的 render
函数若存在,则 Vue 构造函数不会从 template
选项或经过 el
选项指定的挂载元素中提取出的 HTML 模板编译渲染函数。
至此,食材都准备好了,vue大厨开始开工吧!
此时,将template里的内容放到render函数中开始渲染处理,即执行render方法渲染template里的内容。
(这里是对vue的语法进行解析吗?)
题外话:
el其实就是往后要挂载vue组件的一个目标点,若是连目标都找不到,还活着干吗,干脆结束
template/render就是往后要作的事情,若是都不知道本身接下来要去作什么,还活着干吗,干脆也结束
作人,又未尝不是如此。
菜都准备好了总要上桌吧!
全部的dom结构都被渲染好了,vue语法也被解析成正常的html内容了,总要放到页面展现了吧:
3、挂载部分
开始挂载以前,这里提供一个钩子函数,beforeMount挂载前钩子,
编译template里的内容并在虚拟dom中执行,页面上依旧没有任何展现;
挂载中,要作的事就是建立vm$.el,并替换到el元素,
这一段我也不是太理解,大概感受就是将#app的那段空的div换成刚才vue生成好的虚拟dom;
挂载完毕,这里提供一个钩子函数,mounted挂载完毕钩子,
el
被新建立的 vm.$el
替换,并挂载到实例上去
至此,全部的dom结构和数据都被展现到页面当中,
这时能够作一些事情,好比关掉以前展现的loading;
注意: mounted
不会承诺全部的子组件也都一块儿被挂载。若是你但愿等到整个视图都渲染完毕,能够用 vm.$nextTick 替换掉 mounted
mounted: function () { this.$nextTick(function () { // Code that will run only after the // entire view has been rendered }) }
nextTick: 在dom结构更新后使用这个方法获取最新的dom结构
生命周期到这里,也算初步完成了他的使命,
若是是一个纯静态页不作任何修改展现的话,根本不必用到生命周期的后两区块内容了。
可是若是在mounted以后再对实例中的data属性作操做的话,就会走进生命周期的另外一个阶段:更新
4、更新部分
依旧是那个套路,触发了更新的开关后,会给一个开始更新的回调:
更新以前,这里有一个钩子函数,beforeUpdate开始更新前钩子,
在这个钩子里能够提供一个弹窗提示用户确认跟新啥的。或者再展现一个loading;
也能够手动移除已添加的事件监听器
更新中,vue实例要开始将旧数据替换为新数据,在虚拟dom中从新渲染,
虚拟dom开始改变,可是页面这时没有任何变化,由于只是改的虚拟dom,还并未真正修改dom结构;
更新完毕,这里有一个钩子函数,updated更新后钩子,
这时真正的dom结构被完全替换,页面展现上也会发生改变,
在这个钩子里能够提供一个弹窗告诉用户更新完毕。同时去掉loading弹层啥的;
注意: updated
不会承诺全部的子组件也都一块儿被重绘。若是你但愿等到整个视图都重绘完毕,能够用 vm.$nextTick 替换掉 updated
:
updated: function () { this.$nextTick(function () { // Code that will run only after the // entire view has been re-rendered }) }
若是执行了vm.$destory,就会进入到最后一个部分
5、销毁部分
同上
开始销毁vue实例以前,会有一个钩子函数提示开发者组件要开始销毁:beforeDestory开始销毁钩子,
在这个钩子中咱们能够提醒用户是否删除等,或者作一些开发者与业务有关的相关操做;
销毁中,vue这时的主要目标就是卸载,就像人要洗澡前各类脱同样(具体就不要想象了!),
他要卸载在身上的各类监听、各类事件, 各类绑定以及各类子组件实例销毁,感受像毁灭一切
好比watchers(我没用过没有发言权)、子组件child components、事件event;
销毁后,这时再次提供最后一个钩子函数,destoryed销毁完毕,
在这里咱们能够提示用户删除完毕啥的,也能够清空咱们本身的定时器或者作一些其余善后工做;
到这一步,这次整个vue实例的生命周期就完全结束了。
以上,仅是本身了解vue后再刷生命周期图的二次理解,仅表明我的的理解,
不必定彻底正确,欢迎指正,最后也别全信。毕竟绝知此事要躬行。
最后,贴一张一刷时本身备注的官网生命周期图,对照着图再去理解个人总结应该更好。(查看清晰大图:右键新标签页打开)
哇塞,认真学习了16分钟,记录草稿后,加上本身理解对树讲述了两遍后,一口气2000字的心得写下来了。
真的是画竹要先成竹在胸才行!
2018-06-09 14:07:16