尼采般地抒情

尼采般地抒情

尼采般地抒情

音乐盒

站点信息

文章总数目: 321
已运行时间: 1782

前言:本文探讨Vue3框架中createApp函数与mount方法的大致工作机制。首先介绍深入源码的工具和方式,而后介绍vue源码项目架构,最后详述vue创建实例应用的大致流程。

一、前序

1.1 调试准备工作

通过浏览器debugger调试的第一视角,了解代码的执行机制:

  1. vue3源码地址:https://github.com/vuejs/coregit clone到本地,然后执行下面命令即可
pnpm i
pnpm dev
  1. Live Server:vscode下这个插件,目的是运行html文件并提供热更新作用

  1. 会使用浏览器debugger功能,比较常用的有以下几点
    1. 定位源码区域,可以自行设置断点
    2. 变量区域,可以了解执行区域函数里面的具体变量值
    3. 调用栈,可以回溯调用
    4. 命令调试

F8:下一个断点处

F9:下一步如果是调用函数,则进入函数内

F10:下一步如果是调用函数,则跳过函数

F11:和F9作用几乎一致,执行异步代码会进入,F9不会

Shift+F11:跳出当前函数

源码结构

项目结构为monorepo架构方式,更加合理组织项目核心模块

  1. compiler模块:编译
    1. compiler-core:核心编译模块
    2. compiler-dom:依赖compiler-core,处理template标签的,将template内容编译成render函数
    3. compiler-sfc:解析vue文件
    4. compiler-ssr:服务端编译相关
  1. reactivity模块:响应式核心。(通过子包的形式,可以脱离vue环境,单独使用)
  2. runtime模块:运行时
  3. server-renderer:服务端渲染相关
  4. temaplate-explorer:查看模板编译结果
  5. shared:公共方法
  6. vue:框架集成入口

二、createApp

vue选项式api创建一个应用

Vue通过createApp初始化一个Vue实例,然后通过实例方法mount挂载组件。

通过debugger可以走到该部分代码

ensureRenderer

F9进入ensureRenderer函数内部:

其主要功能就是核心渲染相关,负责根据当前运行环境创建一个适合的渲染器:

  • 39行和46行代码:ensureRenderer方法只初始化一次
  • 60行和68行也就是ensureRenderer方法向外暴露出去的接口(rendercreateApp

createAppAPI(ensureRenderer所暴露出来的)

根据ensureRenderer所返回的渲染器执行createAppAPI方法创建一个实例,也就是创建Vue实例对象的核心逻辑所在。

F9进入createAppAPI函数内部:

  • 参数部分:
    • rootComponent:也就是我们所写的选项式API的“选项”

为什么data属性是一个函数而不是一个对象?

  • 避免对象数据污染:如果是对象的话,只是单纯的引用值(通用同一个内存地址,一处修改,其他所有敌方都会改变),如果是函数的话,则是原始值

这部分的data如何响应化?

  • 215行代码:context是用于记录组件的属性
  • 238行代码到384行代码:定义了我们常见的一些API

mount方法的重写

经过ensureRenderer方法和createApp方法所得到的实例对象app,还会经过一次mount的重写,这是为什么呢?

通过解构出上述返回的app对象中的mount,重写了app.mount方法,这个和不同类型的渲染有关,比如说服务端渲染可能需要不同的挂载逻辑。通过重写mount,可以提供一个统一的API接口,这一点也体现了Vue的灵活所在。

  • 77行到103行代码:根据传进的需要挂载的DOM id值,读取DOM处理前的内容将其编译为供后续生成DOM需要的component对象

深入应用实例mount方法

mount内部,了解一下mount挂载全过程:

  • 310行代码:实例挂载只能挂载一次
  • 319行代码:根据“选项” 生成虚拟节点(vnode),同时将上述的context赋值给虚拟节点,至此,我们常说的虚拟节点到渲染真是节点的虚拟节点部分完成了

响应式也在该部分内部完成

    • _createVNode
    • createBaseVNode:这里有了vnode,但是没有实例(app._instance)
  • 343行代码:if条件里面是服务端渲染相关,暂不考虑,走到else的真实DOM渲染逻辑,也就是render逻辑
  • 346行代码:渲染
  • 349行代码:最后记录挂载的容器信息:_container

render

mount方法内部会调用render函数来将传入的模板(template或者render函数构建)生成虚拟DOM,然后通过对虚拟DOM的处理将其转换成实际的DOM结构并插入到页面中

F9走进render函数内部:

  • 参数部分
    • vnode:待渲染的虚拟节点
    • container:页面挂载容器
    • namespace
  • 2362行代码:转换的核心逻辑,其主要逻辑就是对两个虚拟节点进行diff比较,比较出差异部分再按需更新真实DOM节点

挂载前后对比

以下就是通过vue渲染前后的对比页面


评论区

什么都不舍弃,什么也改变不了