参考原文:https://m.html.cn/qa/vue-js/22535.html
Vue 中 生命周期钩子函数分别做了什么?
beforeCreate执行时:data / el 未初始化,值为undefined
created执行时:可得到 data 的值,但 根 dom元素 el 还未初始化。
可对 data 进行操作,进行数据请求将返回的数据赋给 data。
beforeMount执行时:data / el 已初始化,但此时 el 并没有渲染进数据,el 的值为“虚拟”的元素节点
mounted执行时:el 已渲染完成并挂载到实例上
对挂载的 dom 进行操作,此时,dom已被渲染到页面上。
beforeUpdate 和 updated 触发时:el 中的数据已渲染完成,但只有 updated钩子被调用时,组件dom才被更新。
虽然updated函数会在数据变化时被触发,但却不能准确的判断是哪个属性值被改变,所以在实际情况中用 computed / watch 来监听属性的变化,并做一些其他的操作。
所有的生命周期钩子自动绑定 this 上下文到实例中,所以不能使用箭头函数来定义一个生命周期方法(例如:created: () => this.fetchTodos() ),会导致this指向父级
在使用vue-router 时,有时需要使用缓存组件状态,这时候created钩子就不会被重复调用,如果子组件需要在每次加载或切换状态的时候进行某些操作,可以使用 activated 钩子触发。
注意:activated,deactivated 是组件 keep-alive 时独有的钩子
父子组件的钩子并不会等待请求返回,请求是异步的,VUE 设计也不能因为请求没有响应而不执行后面的钩子。所以,我们必须通过 v-if 来控制子组件钩子的执行时机。
注意:
在父组件的 created 中发请求获取数据,通过props传递给子组件。子组件在 created 或者mounted中拿父组件传递过来的数据 ,这样处理是有问题的。
在父组件调用接口传递数据给子组件时,接口响应显然是异步的。这会导致无论你在父组件哪个钩子发请求,在子组件哪个钩子接收数据。都是取不到的。当子组件的mounted都执行完之后,此时可能父组件的请求才返回数据。会导致:从父组件传递给子组件的数据是 undefined
解决方法1 :
在渲染子组件的时候加上一个条件,data1 是父组件调用接口返回的数据。当有数据的时候再去渲染子组件。这样就会形成天然的阻塞。在父组件的 created 中的请求返回数据后,才会执行子组件的 created,mounted。最后执行父组件的mounted。
<div class="test"> <children v-if="data1" :data="data1" /> </div>
解决方法2:
在子组件中 watch 监听,父组件获取到值,这个值就会变化,自然是可以监听到的。
从父组件点击调用接口并显示子组件,子组件拿到数据并监听在 watch 中调用方法并显示
以下为子组件。data1 是从父组件传递过来的数据。在 created,mounted中都拿不到父组件调用接口返回的data1。只能 watch 监听 data1,并调用方法渲染子组件。
props:['data1'], watch:{ data1:{ deep: true, handler: function(newval, oldval){ this.$nextTick(() => { this.data1 = newval this.showData1(this.data1) }) } } }
Vue 的 父子组件的生命周期执行顺序
Vue 的父组件和子组件的生命周期钩子函数执行顺序可以归类为以下 4 部分:
1、加载渲染过程
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子beforeMount -> 子 mounted -> 父 mounted
注意:mounted 不会保证所有的子组件也都被一起挂载。如果希望等到整个视图都渲染完毕,可以在 mounted 内部使用 vm.$nextTick
2. 父组件更新过程
父 beforeUpdate -> 父 updated
3. 子组件更新过程
父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
4. 销毁过程
父 beforeDestroy -> 子 beforeDetroy -> 子 destroyed -> 父 destroyed