Advanced-Frontend/Daily-Interview-Question

第 78 题:Vue 的父组件和子组件生命周期钩子执行顺序是什么

Opened this issue · 18 comments

  1. 父组建: beforeCreate -> created -> beforeMount
  2. 子组件: -> beforeCreate -> created -> beforeMount -> mounted
  3. 父组件: -> mounted
  4. 总结:从外到内,再从内到外
luchx commented
  1. 加载渲染过程
    父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
  2. 子组件更新过程
    父beforeUpdate->子beforeUpdate->子updated->父updated
  3. 父组件更新过程
    父beforeUpdate->父updated
  4. 销毁过程
    父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

1.首次加载过程
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount ->
子mounted -> (子activated) -> 父mounted
2.父组件更新过程
父beforeUpdate -> (子deactivated) -> 父updated
3.子组件更新过程
父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated
4.销毁过程
父beforeDestroy-> 子beforeDestroy -> 子destroyed -> 父destroyed

和事件流好像啊

Note that mounted does not guarantee that all child components have also been mounted. If you want to wait until the entire view has been rendered, you can use vm.$nextTick inside of mounted:

^_^

在vue里面父的mounted并不一定在子mounted之前。这是官方已经明确的。而且在开发中也是需要避免这个问题的。

  1. 加载渲染过程
    父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
  2. 子组件更新过程
    父beforeUpdate->子beforeUpdate->子updated->父updated
  3. 父组件更新过程
    父beforeUpdate->父updated
  4. 销毁过程
    父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

你好! 请问具体为什么 这么处理啊?

子组件更新,子beforeUpdate->子updated,并不会直接触发父组件钩子
单向数据流呀

@zeroone001
1,父组件:beforeDestroy,
2,子组件:beforeDestroy->destroyed,
3,父组件:destroyed

vue的生命周期:beforeCreate created beforeMount mounted beforeDestory destoryed beforeUpdate updated

父组件和子组件钩子执行顺序

  1. 加载渲染过程:父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
    父组件挂载完毕肯定是等里面的子组件都挂载完毕后才算父组件挂载完毕了,所以父组件的mounted在最后。
  2. 子组件更新过程(子组件更新影响到父组件的情况):父beforeUpdate -> 子beforeUpdate->子updated -> 父updted
    子组件更新过程(子组件更新不影响父组件的情况):子beforeUpdate -> 子updated
  3. 父组件更新过程(父组件影响子组件的情况):父beforeUpdate -> 子beforeUpdate->子updated -> 父updted
    父组件更新过程(父组件不影响子组件的情况):父beforeUpdate -> 父updated
  4. 销毁过程:父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
  1. 加载渲染过程
    父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
  2. 子组件更新过程
    父beforeUpdate->子beforeUpdate->子updated->父updated
  3. 父组件更新过程
    父beforeUpdate->父updated
  4. 销毁过程
    父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

@luchx 谢谢你的回答,我对2,3不太理解。如果一个页面 app组件-> main组件 ->footer组件-> btn组件 ,当btn组件更新的时候,是这样的更新过程吗?
footer组件beforeUpdate -> btn组件beforeUpdate -> btn组件updated -> footer组件updated
如果是的话,当footer组件beforeUpdate、updated的时候,main组件和app组件是也会走这样的更新过程吗。

luchx commented

@luchx 谢谢你的回答,我对2,3不太理解。如果一个页面 app组件-> main组件 ->footer组件-> btn组件 ,当btn组件更新的时候,是这样的更新过程吗?
footer组件beforeUpdate -> btn组件beforeUpdate -> btn组件updated -> footer组件updated
如果是的话,当footer组件beforeUpdate、updated的时候,main组件和app组件是也会走这样的更新过程吗。

@habc0807

  1. 如果只是btn组件更新是只会触发btn组件的生命周期,也就是btn组件: beforeUpdate -> updated
  2. 父子组件的更新依赖执行顺序是在于全局状态的更新,比如通过props传递,或者vuex等存在数据流向触发的更新,那么更新顺序就是父beforeUpdate->子beforeUpdate->子updated->父updated

希望以上回答能解决你的困惑 : )

还有异步组件的情况 没人讨论吗

  1. 父组建: beforeCreate -> created -> beforeMount
  2. 子组件: -> beforeCreate -> created -> beforeMount -> mounted
  3. 父组件: -> mounted
  4. 总结:从外到内,再从内到外

您好,为什么我在本地打印出来,是:
父组件beforeMount->父组件mounted->子组件beforeMount->子组件mounted?
但是销毁的时候又是正常的:
父组件beforeDestroy->子组件beforeDestroy->子组件destroyed->父组件destroyed

还有异步组件的情况 没人讨论吗

因为异步组件就没有固定的周期了,如果钩子中有异步函数的话,子组件的mounted是在父组件执行完之后,我一般是在子组件中用selterval判断父组件时候已经有数据,然后再执行方法

yayxs commented

04-vue 生命周期进阶

基本流程

  • new vue 创建实例
  • 初始化事件 生命周期
  • beforeCreate
  • 初始化 注入校验
  • created
  • 是否指定 el
    • 否: 调用 vm.$mount(el)
    • 是:是否指定template
      • 否 将el 外部的html 作为template 编译
      • 是 将 template 编译到render
  • beforeMount
  • 创建vm.$el 并用其替换el
  • mounted
  • 挂载完毕
  • 当data 修改的时候:
    • beforeUpdate
    • updated
  • 调用vm.$destroy()
  • beforeDestroy
  • 解除绑定 销毁子组件 事件监听
  • 销毁完毕
  • destroyed

加载渲染的过程

父组件挂载完毕肯定是等里面的子组件都挂载完毕后才算父组件挂载完毕了,所以父组件的mounted在最后。

子组件更新过程

子组件更新过程(子组件更新影响到父组件的情况):父beforeUpdate -> 子beforeUpdate->子updated -> 父updted
子组件更新过程(子组件更新不影响父组件的情况):子beforeUpdate -> 子updated

父组件更新过程

20200421221422

eactivated函数的触发时间是在视图更新时触发。因为当视图更新时才能知道keep-alive组件被停用了。

父组件更新过程(父组件影响子组件的情况):父beforeUpdate -> 子beforeUpdate->子updated -> 父updted
父组件更新过程(父组件不影响子组件的情况):父beforeUpdate -> 父updated

销毁过程

父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

小补充

deactivated keep-alive 组件停用时调用。
activated keep-alive 组件激活时调用。

总结

Vue父子组件生命周期钩子的执行顺序遵循:从外到内,然后再从内到外,不管嵌套几层深,也遵循这个规律

为什么我在控制台输出的顺序是父组件 mouted 之后 子组件 才 顺序执行生命周期呢 哪位大佬帮孩子解释一下原理呗

  1. 父组建: beforeCreate -> created -> beforeMount
  2. 子组件: -> beforeCreate -> created -> beforeMount -> mounted
  3. 父组件: -> mounted
  4. 总结:从外到内,再从内到外

由于父组件是包裹了子组件, 所以顺序很简单, 无论是创建, 挂载还是更新和卸载, 这些操作的开始都是从父组件进入, 父组件必须等待子组件完成自身的操作后父组件才能完成自己对应的操作, 所以结束是先从子组件完成的.

vue源码哪里可以看到父组件要等待子组件完成之后 才处罚自身装载啊