创建的钩子是再初始化的时候执行的,callHook这个函数就是用for循环,执行一下定义的钩子
beforeMounted是再mountComponent中执行的,然后执行到_update时执行patch,然后执行createElm然后执行createComponent。
最开始会执行第一步,即init,然后执行createComponentInstanceForVnode,这个时候,会执行子组件的init操作,结束之后执行$mount操作,然后执行mountComponent...
执行完init后会执行函数initComponent,然后继续执行invokeCreateHooks,往insertedVnodeQueue里面插入子Vnode
然后执行insert操作插入
执行完createComponent后,回到createElm函数,执行完createElm,然后返回patch继续执行
invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch),然后遍历insertedVnodeQueue执行insert钩子,再insert钩子中执行mounted
捋一捋主线逻辑
①new Vue初始化再init中执行 :父beforeCreated->父created
②然后挂载时mountComponent中执行:父beforeCreated->父created->父beforeMounted
③patch->createElm->createComponent执行init钩子
initi中执行createComponentInstanceForVnode:父beforeCreated->父created->父beforeMounted->子beforeCreated->子created
init中执行$mount:父beforeCreated->父created->父beforeMounted->子beforeCreated->子created
子beforeMounted
④此时子元素执行到$mount,我们再加一个孙元素,同第二步开始然后孙元素执行到$mount,此时对应的执行顺序为:
父beforeCreated->父created->父beforeMounted->子beforeCreated->子created
子beforeMounted->孙beforeCreated->孙created->孙beforeMounted
⑤孙节点执行完$mount,即执行完init钩子,回到createComponent执行initComponent,往insertedVnodeQueue插入Vnode,此时insertedVnodeQueue为[孙Vnode]
⑥孙节点然后执行insert等后续操作,我么从子节点逻辑到父节点逻辑是再init执行$mount时,所以,当孙节点执行完,我们又回到了子节点的init,执行完子节点init,同第五步,插入子Vnode,此时insertedVnodeQueue为[孙Vnode, 子Vnode]
⑦当子节点执行完createComponent,然后回到createElm,执行完之后,回到patch执行invokeInsertHook,然后执行中insertedVnodeQueue的inser钩子,insert钩子中执行mounted操作,所以先执行孙Vnode的mounted再执行子的,此时顺序为:
父beforeCreated->父created->父beforeMounted->子beforeCreated->子created
子beforeMounted->孙beforeCreated->孙created->孙beforeMounted->孙mounted->子mounted
⑧由于父,其实就是大Vue,它不同于其他组件,执行完子mounted之后,即执行完_update,然后回到updateComponent函数中,继续往下执行,然后会有一个vm.$vnode == null条件,大Vue满足,所以执行mounted操作,此时顺序为:
父beforeCreated->父created->父beforeMounted->子beforeCreated->子created
子beforeMounted->孙beforeCreated->孙created->孙beforeMounted->孙mounted->子mounted->父mounted
注意由于父是大Vue,所以他的钩子会被merget到其他子组件的mounted中,所以再执行子mounted时,Vue定义的mounted也会被执行