<script src="../../dist/vue.global.js"></script>
<div id="demo">
<h1>
{{count}}
</h1>
</div>
<script>
const { createApp, ref,toRefs, reactive, onUpdated, onMounted,onBeforeMount,onBeforeUpdate} = Vue
var app = createApp({
setup(){
var count = ref(1)
onBeforeMount(()=>{
debugger
})
onMounted(()=>{
debugger
count.value++
})
onBeforeUpdate(()=>{
debugger
})
onUpdated(()=>{
debugger
})
return {
count,
}
},
beforeCreate(){
debugger
},
created(){
debugger
},
beforeMount(){
debugger
},
mounted(){
debugger
},
beforeUpdate(){
debugger
},
updated(){
debugger
},
beforeUnmount(){
debugger
},
unmounted(){
debugger
}
})
app.mount('#demo')
setTimeout(()=>{
app.unmount()
},1000)
</script>
依次跳出断点可以发现出钩子函数的执行顺序 如下
beforeCreate
-> created
->onMounted ->mounted
->onBeforeUpdate ->beforeUpdate
->onUpdated ->updated
->onbeforeUnmount ->beforeUnmount
->onUnmounted ->onMounted
先来看看beforeCreate是在什么时候执行的,且beforeCreate 和 created之间都做了那些事情?
如下图所知,beforeCreate的执行关联到了setupComponent,直到执行了applyOptions,在beforeCreate 和 created之间对用户转入的options做了处理,比如对data做reactive处理,对methods遍历到ctx上,且绑定this
beforeCreate
created
mounted 和 onMounted,flushPostFlushCbs内部遍历pendingPostFlushCbs分别执行,这里的if(m) 其中m是一个数组,是多个onMounted钩子
flushPostFlushCbs执行如下图所示
接下来我们来看看 onMounted是如何收集回调钩子的,如下图打上断点,然后找到下一个满足条件断点调用栈,就知道vue2写法的mounted钩子是如何处理的,他是在applyoptions时候进行了registerLifecycleHook(onMounted, mounted)
,
mounted是用户写的函数
beforeUpdate,如下图可知
updated
跟mounted类似的流程
if (m) {
queuePostRenderEffect(m, parentSuspense)
}
if (u) {
queuePostRenderEffect(u, parentSuspense)
}
onBeforeUnmount
当执行了app.unmount()时候
onUnmounted
跟mounted 和 updated类似的流程
if (m) {
queuePostRenderEffect(m, parentSuspense)
}
if (u) {
queuePostRenderEffect(u, parentSuspense)
}
if (um) {
queuePostRenderEffect(um, parentSuspense)
}
我们声明的钩子函数 全都给声明到了实例的m等相关的属性上,且他们的值都是数组,因为可以使用多个