1.执行createApp

  1. 执行ensureRenderer去判断是否有渲染器,首次进入是没有渲染器的。所以会调用createRenderer函数创建渲染器
  2. 创建渲染器的时候最终会返回一个对象,包括render、hydrate、createApp
    a. hydrate做服务端渲染
    b. render函数
    c. createApp会调用createAppAPI函数
  3. createAppAPI函数的调用,会返回createApp函数
  4. createApp函数返回一个包括App全局API的对象,包括use、mixins、component、directive、mount、unmount、provide

2.创建和渲染App的Vnode

  1. 在调用mount函数时,我们先将createApp的mount函数进行保存,如何进行重写,目的是为了能够跨平台。
    a. 重写的normalizeContainer方法就是在web端获取我们的元素,依据我们的选择器。创建container。
    b.先清空原有的container中的内容,如何调用保存的mount函数(与平台无关的代码)。
  2. mount函数内部首先使用createVNode创建vnode对象
  3. 调用render函数把vnode传进去渲染vnode
  4. 在render函数中判断vnode是否为null,如果是null则调用unmount函数卸载组件,否则调用patch函数挂载组件
  5. patch函数依据vnode的新老节点不同情况进行不同处理
    a.如果新的节点和旧的节点类型不同, 那么会销毁整个子节点树
    b.处理文本节点:processText
    c.处理注释节点:processCommentNode
    d.处理静态节点:mountStaticNode、patchStaticNode
    e.处理Fragment组件节点:processFragment
    f.处理普通的DOM元素:processElement
    g.处理组件节点:processComponent

3.挂载App

  1. 第一次挂载根组件调用processComponent,由于此时没有老节点所以会调用mountComponent进行组件的挂载
  2. mountComponent调用createComponentInstance创建组件实例
  3. 再调用setupComponent函数对组件实例的数据进行初始化。
  4. 并且调用setupRenderEffect设置有副作用的函数(相当于依赖的收集)
    a.在此函数中创建响应式的副作用渲染函数,effect。
    b.effect的作用是当组件的数据发生变化时, effect函数包裹的内部函数componentEffect会重新执行一遍, 重新渲染组件
    c.在effect中会判断组件实例是否已经挂载,如果已挂载,则进行组件的更新,会调用patch函数。
    d.未挂载:
1.调用renderComponentRoot渲染组件,生成子树的vnode
2.使用patch函数把子树的vnode挂载到container中
3.将组件挂载状态改为已挂载
  1. patch函数,组件内部是普通节点时processElement调用mountElement(挂载节点)patchElement(更新节点)。以下说明挂载节点
    a.从vnode中读出属性
    b.根据属性创建DOM元素节点
    c.如果子节点是数组则会调用mountChildren来处理子节点的children
    d.处理好其他属性
    e.将最后的el挂载到container上。
    在这里插入图片描述

题目:

1.组件的VNode和组件的instance有什么区别?

Vnode:虚拟节点
instance:保存组件各种状态 data/setup/computed/methods...

2.为啥vue3会有多个根

vue3在外面包裹了一个Fragment

3.组件初始化setupComponent(instance)过程

处理props、attrs
处理slots
执行setup:const rst =setup()  instance.setupSate = proxyRefs(rst) 
编译template——> compile :  <template>  ——> render函数
对vue2的options api进行支持

4.对于template的编译,优化点

1.对于不会改变的静态节点,vue会在编译阶段进行作用域提升,先使用createVNode生成之后再加入到render中
	vue是组件级的更新,这样我们在更新的使用调用render则不需要再创建静态节点,减少了性能的消耗。
2.非静态节点保存到一个数组中,在patch阶段的时候只对非静态节点进行diff。
	render函数中会调用_openBlock函数,此函数会讲动态节点添加到dynamicChildren数组中(BlockTree的概念)
Logo

前往低代码交流专区

更多推荐