vue 有两个阶段   分为编译时 和运行时

webpack    把vue模板编译生成对应的js代码,vue组件组件对应的template模板会被编译器转化为render函数。 

运行时

编译后代码执行render函数 并返回VNode,最后将VNode 渲染成真实的DOM节点

createApp > ensureRenderer > createRenderer > baseCreateRenderer > createAppApi > mount

// overload 1: no hydration
function baseCreateRenderer<
  HostNode = RendererNode,
  HostElement = RendererElement
>(options: RendererOptions<HostNode, HostElement>): Renderer<HostElement>

// overload 2: with hydration
function baseCreateRenderer(
  options: RendererOptions<Node, Element>,
  createHydrationFns: typeof createHydrationFunctions
): HydrationRenderer


createApp 函数调用 ensureRenderer 函数  ensureRenderer 函数调用

createRenderer 函数 createRenderer 函数调用baseCreateRenderer函数 

baseCreateRenderer 返回 

return {
  render,
  hydrate,
  createApp: createAppAPI(render, hydrate)
}

  函数执行

  1. const patch = () => {} // 核心diff过程
  2. const processElement = () => {} // 处理element
  3. const mountElement = () => {} // 挂载element
  4. const mountChildren = () => {} // 挂载子节点
  5. const processFragment = () => {} // 处理fragment节点
  6. const processComponent = () => {} // 处理组件
  7. const mountComponent = () => {} // 挂载组件
  8. const setupRenderEffect = () => {} // 运行带副作用的render函数
  9. const render = () => {} // 渲染挂载流程

createAppAPI 工厂函数创建app

createAppAPI返回的createApp函数才是真正创建应用的入口。在createApp里会创建vue应用的上下文,同时初始化app,并绑定应用上下文到app实例上,最后返回app

重写mount方法

  1. // 创建vue应用上下文
  2. const context = createAppContext();


  1. const createApp = ((...args) => {
  2. // ...
  3. const { mount } = app; // 缓存最初的mount方法
  4. // 重写mount
  5. app.mount = (containerOrSelector) => {
  6. // 获取容器
  7. const container = normalizeContainer(containerOrSelector);
  8. if (!container) return;
  9. const component = app._component;
  10. // 判断如果传入的根组件不是函数&根组件没有render函数&没有template,就把容器的内容设置为根组件的template
  11. if (!isFunction(component) && !component.render && !component.template) {
  12. component.template = container.innerHTML;
  13. }
  14. // 清空容器内容
  15. container.innerHTML = '';
  16. // 执行缓存的mount方法
  17. const proxy = mount(container, false, container);
if (container instanceof Element) {
  container.removeAttribute('v-cloak')
  container.setAttribute('data-v-app', '')
}
  1. return proxy;
  2. };
  3. return app;
  4. });

重写mount 方法 

完成渲染