天天看点

vue3初始化过程(实例创建和挂载)

实例创建,实例挂载

  1. vue-3.2.30\packages\vue\examples\composition

    新建test.html文件,内容如下:
<script src="../../dist/vue.global.js"></script>
<div id="demo">
  <section>
    <h1>{{count}}</h1>
  </section>
</div>
<script>
  const { createApp, ref } = Vue
  var app = createApp({
    setup() {
      const count = ref(1)
      return { count }
    }
  })
  app.mount('#demo')
</script>
           
  1. 按住

    ctrl + p

    ,输入

    runtime-core/src/apiCreateApp.ts

    ,回车找到该文件
  2. 按住

    ctrl + f

    ,输入

    function createApp(rootComponent

    ,回车找到该文件位置,在浏览器中给该位置打断点
//用户执行了创建实例代码,其实是为了得到app实例对象,
//就是执行了一下函数createAppAPI内部返回的createApp方法,
//且返回app实例,app实例是一个对象,上面也挂载了mount等方法
 var app = createApp({})
           
  1. 按住

    ctrl + f

    ,输入

    const vnode = createVNode(

    ,回车找到该文件位置,在浏览器中给该位置打断点
  2. 按住

    ctrl + f

    ,输入

    render(vnode, rootContainer, isSVG)

    ,回车找到该文件位置,在浏览器中给该位置打断点
// 当执行挂载方法 就会触发步骤4 和 步骤5的断点
app.mount('#demo')
           
  1. 按住

    ctrl + p

    ,输入

    runtime-core/src/renderer.ts

    ,回车找到该文件
  2. 按住

    ctrl + f

    ,输入

    createAppAPI(render, hydrate)

    ,回车找到该文件位置,按住

    ctrl+左键

    点击

    render

    函数,找到

    render

    函数的声明的位置
  3. 按住

    ctrl + f

    ,输入

    patch(container._vnode

    ,回车找到该文件位置,打上断点
const render = (vnode, container, isSVG) => {// 首次vnode有值
  if (vnode == null) {
    if (container._vnode) {
      unmount(container._vnode, null, null, true)
    }
  } else { // 首次container._vnode 没有值
    patch(container._vnode || null, vnode, container, null, null, null, isSVG)
  }
  flushPostFlushCbs()
  container._vnode = vnode // 首次container._vnode被赋值,供给下一次使用
}
           
  1. 按住

    ctrl + 左键

    ,点击

    patch

    函数,找到

    patch

    函数声明的位置
  2. 按住

    ctrl + f

    ,输入

    processElement(

    ,回车找到该文件位置,打上断点
  3. 按住

    ctrl + f

    ,输入

    processComponent(

    ,回车找到该文件位置,打上断点
  4. 只留步骤10 和 步骤11两个断点,刷新页面,点击

    Resume script execution

    ,可以看到patch的递归过程
  5. 按住

    ctrl + f

    ,输入

    createComponentInstance(

    ,回车找到该文件位置,打上断点,创建实例
  6. 按住

    ctrl + f

    ,输入

    setupComponent(instance)

    ,回车找到该文件位置,打上断点,初始化工作执行setup,并且将结果响应式化
    • initProps
    • initSlots
    • setupStatefulComponent
  7. 按住

    ctrl + f

    ,输入

    setupRenderEffect(

    , 回车找到该文件位置,打上断点,
  8. 按住

    ctrl + p

    ,输入

    runtime-core\src\component.ts

    ,回车找到该文件,
  9. 按住

    ctrl + f

    ,输入

    proxyRefs(setupResult)

    ,回车找到该文件位置,打上断点,将

    setup

    函数执行的结果

    setupResult

    ,做代理,然后赋值给

    instance.setupState

    浓缩版代码流程
const createApp = function(...args){
    const app = ensureRenderer().createApp(...args)
    const mount = app.mount
    app.mount = function(v){
        return mount(v)
    }
    return app
}
           
let renderer;
function ensureRenderer(){
    return (renderer || renderer = createRenderer())
}
           
function createRenderer(){
    return baseCreateRenderer()
}
           
function baseCreateRenderer(){
    const render = (vnode,container,isSVG){
        if(vnode == null){
            if(container._vnode){
                unmount(container._vnode,null,null,true)
            } else{
                patch(container._vnode || null,vnode,container,null,null,null,isSVG)
            }
        }
    }
    return {
        render,
        createApp:createAppAPI(render) // createApp()时,就会执行createAppAPI函数
    }
}
           
function createAppAPI(render){
    const context = createAppContext()
    return function createApp(rootComponent,rootProps = null){ // createApp()时,返回app
        const app = (context.app = {
            mount(rootContainer){// 等到用户调用了app.mount()才会执行内部的mount函数
                const vnode = createVNode(
                    rootComponent,
                    rootProps
                )
                render(vnode,rootContainer,isSVG)
            }
        })
        return app 
    }
}
           

流程图

vue3初始化过程(实例创建和挂载)

vue3源码流程图 | ProcessOn在线思维导图

vue3源码流程图 - ProcessOn

继续阅读