有点搞不懂 patch 中 createComponent 中的 i.init 等这些 hook 被注册和被调用的顺序了
来源:3-3 patch(上)
染丶墨3614535
2021-04-26
我想知道下面结构中 child 组件的 i.init hook 被调用之前是在什么时机被注册的(PS:我知道注册的代码片段是 installComponentHooks,只是我断点想不通注册和调用的先后顺序):
<div id="app">
<child :msg="msg"></child>
</div>
我看到的顺序是这样的
- 从 app 根节点的 patch 开始,patch 中 createElm 创建根 div 后,然后因为 app 这个根节点不是组件,所以会进入后面的 createChildren 方法创建子组件,这时候 createChildren 中的 createElm 执行后会进入 createComponent,然后就开始调用 i.init hook 了;这里我有疑惑;就是这个 hook 我看到是在 create-component.js 文件中的 createComponent 方法中的 installComponentHooks 方法中注册的 hook;但是我看到这里的 createComponent 其实是走的
$mount -> mountComponent -> _render中的$createElement中进入到这个 createComponent 的;这里我开始不懂了;因为组件的$mount是要在 i.init hook 中的 createComponentInstanceForVnode 之后才会调用child.$mount方法;但是 hook 又是在 createComponent 中注册的;我就被绕晕了,怎么感觉child.$mount还没调用,组件自己的 hook 就已经注册好了;我感觉我应该是我印象中的父子顺序出现了问题; - 不知道黄老能不能看懂我的疑惑;
写回答
1回答
-
举个例子,模板
<div id="app">
<hello></hello>
</div>
会编译成 render 函数function render() {
with(this) {
return _c('div', {
attrs: {
"id": "app"
}
}, [_c('hello')], 1)
}
}
render 函数执行的时候就会执行 _c 也就是 createElement 函数创建 vnode 节点,其中 hello 标签并非保留标签,会尝试从 components 中拿,如果注册了,就当成自定义组件执行 createComponent 方法,在执行这个函数的过程中,就会执行 installComponnetHooks 给渲染数据中添加这些钩子函数,比如 init,所以在后续 patch App 组件的时候,遍历遇到 hello 这个组件 vnode 节点,就可以执行这个 init 函数了。142021-04-26
相似问题