vue生命周期详解

1.vue基本生命周期

lifecycle.png

vue源码中最终执行生命周期函数都是调用callHook方法,callHook函数的逻辑很简单,根据传入的生命周期类型 hook,去拿到 vm.$options[hook]对应的回调函数数组,然后遍历执行,执行的时候把 vm作为函数执行的上下文。

1. new Vue(options):创建一个vm实例;

2. mergeOptions(resolveConstructorOptions(vm.constructor), options, vm):合并Vue构造函数里options和传入的options或合并父子的options。比如:在mergeOptions函数中会调用mergeHook方法合并生命周期的钩子函数,mergeHook方法原理是只有父时返回父,只有子时返回数组类型的子。父、子都存在时,将子添加在父的后面返回组合而成的数组。这也是父子均有钩子函数的时候,先执行父的后执行子的的原因;

3. initLifecycle(vm)、initEvents(vm)、initRender(vm):在创建的vm实例上初始化生命周期、事件、渲染相关的属性;

4. callHook(vm, 'beforeCreate'):调用beforeCreate生命周期钩子函数;

5. initInjections(vm)、initState(vm)、initProvide(vm):初始化数据:inject、state、provide。initState 的作用是初始化 props、data、methods、watch、computed 等属性;

6. callHook(vm, 'created'):调用created生命周期钩子函数;

7. vm.$mount(vm.$options.el)$mount方法在多个文件中都有定义,如"src/platform/web/entry-runtime-with-compiler.js"、"src/platform/web/runtime/index.js"、"src/platform/weex/runtime/index.js"。因为$mount方法的实现是和平台、构建方式相关的。以"entry-runtime-with-compiler.js"为例,关键步骤是查看vm.$options中是否有render方法,如果没有则会根据el和template属性确定最终的template字符串,再调用compileToFunctions方法将template字符串转为render方法,最后,调用原先原型上的$mount方法,即开始执行"lifecycle.js"中mountComponent方法;

8. callHook(vm, 'beforeMount'):调用beforeMount生命周期钩子函数;

9. vm._render() => vm._update() => vm.__patch__():先执行vm._render方法,即调用createElement生成虚拟DOM,即VNode ,每个VNode有children ,children 每个元素也是⼀个 VNode,这样就形成了⼀个 VNode Tree;再调用vm._update方法进行首次渲染,vm._update方法核心是调用vm.patch方法,这个方法跟vm.$mount一样跟平台相关;vm.patch方法则是根据生成的VNode Tree递归createElm方法创建真实Dom Tree挂载到Dom上;

10. callHook(vm, 'mount'):调用mount生命周期钩子函数:VNode patch 到 Dom 之后会执行 'invokeInsertHook'函数,把insertedVnodeQueue中保存的mount钩子函数执行一遍,insertedVnodeQueue队列中的钩子函数是在根据VNode Tree递归createElm方法创建真实Dom Tree过程生成的钩子函数顺序队列,因此mounted钩子函数的执行顺序是先子后父;

11. data changes:数据更新,nextTick中执行flushSchedulerQueue方法,该方法会执行watcher队列中的watcher;

12. callHook(vm, 'beforeUpdate'):执行watcher时会执行watcher的before方法,即调用beforeUpdate生命周期钩子函数;

13. Virtual DOM re-render and patch:重新render生成新的Virtual DOM,并且patch到DOM上;

14. callHook(vm, 'updated'):调用updated生命周期钩子函数;

15. vm.$destroy():启动卸销毁过程;

16. callHook(vm, 'beforeDestroy'):调用beforeDestroy生命周期钩子函数;

17. Teardown watchers, childcomponents and event listeners:执行一系列销毁动作,在 $destroy 的执行过程中,它又会执行vm.__patch__(vm._vnode, null) 触发它子组件的销毁钩子函数,这样一层层的递归调用,所以 destroyed 钩子函数执行顺序是先子后父,和 mounted 过程一样。

18. callHook(vm, 'destroyed '):调用destroyed 生命周期钩子函数。

2. errorCaptured生命周期钩子函数

  • 当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。

  • 如果一个组件的继承或父级从属链路中存在多个 errorCaptured 钩子,则它们将会被相同的错误逐个唤起。

  • 默认情况下,如果全局的 config.errorHandler 被定义,所有的错误仍会发送它,因此这些错误仍然会向单一的分析服务的地方进行汇报。

3. keep-alive组件

  • keep-alive组件是vue的内置抽象(abstract)组件,抽象组件在initLifecycle过程中 组件实例建立父子关系时会被忽略,因此他自身不会渲染一个DOM元素,也不会出现在父组件链中。

  • keep-alive作用是用于包裹动态组件,缓存不活动的组件实例。keep-alive自定义实现了render函数并利用了插槽slot,render函数中先获取它的默认插槽,再获取到它的第一个组件子节点,因此keep-alive组件只处理第一个子元素,所以一般和它搭配使用的有component动态组件或者router-view。

  • keep-alive组件在created钩子中定义了 this.cache 和 this.keys,本质上是去缓存已创建的 vnode,缓存策略采用LRU策略,每次缓存命中时将当前vnode移到缓存数组末尾,需要删除时则删除缓存数组第一个vnode。

  • keep-alive组件接收三个props:

    1. include:数组、字符串或者正则表达式,只有匹配的组件才会缓存。

    2. exclude:数组、字符串或者正则表达式,任何匹配的组件都不会被缓存。

    3. max:字符串或数字,指定可以缓存的组件最大个数,如果个数超过max,则销毁缓存数组中的第一个组件。

  • keep-alive组件子组件渲染机制:

    1. 首次渲染:和普通组件一样执行正常的init生命周期钩子函数,同时将生成的vnode缓存到内存中;

    2. 组件切换:切换到新组件时,旧组件不会销毁,而是变成未激活状态,即不会执行destroy相关的钩子函数,而是执行 deactivated 生命周期钩子函数,如果新组件不在缓存数组中,则执行首次渲染,否则执行缓存渲染;

    3. 缓存渲染:缓存渲染即组件由未激活状态变成激活状态,因此不会执行created、mounted等钩子函数,而是执行 activated 生命周期钩子函数。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342