Vue3 源码导读(推荐)


Posted in Javascript onOctober 14, 2019

5号凌晨,尤雨溪公布了 Vue 3 源代码。

Vue3 源码导读(推荐)

话不多说,我们趁热对 Vue 3 源码进行一些简要的分析。

如果你还没有阅读过Composition API RFC,可能无法完全看懂下面的内容。

兼容性

目前打包后的代码是 ES2015+,不支持 IE 11。

对 TypeScript 的使用

目前的代码 98% 以上使用 TypeScript 编写。

如果你还没有学习 TypeScript,请尽快学习,否则可能看不懂源码。

另外有件事情说出来可能会让你非常惊讶,Vue 3 的源代码完全没有使用 class 关键字!(只在测试代码和示例代码里用到了 class 关键字)

什么时候发正式版

目前 Vue 3 处于 Pre-Alpha 版本。后面应该还会有 Alpha、Beta 等版本。

根据 Vue 官方时间表,至少要等到 2020 年第一季度才有可能发布 3.0 正式版。

阅读建议

强烈推荐大家用国庆假期这段时间把 Vue 3 的源码通看一遍,因为目前的代码结构清晰,而且代码量相对较少。

下载代码后,使用 yarn dev 命令就可以对其进行调试。(有人给出了详细的调试技巧)

关于阅读顺序,我的建议是

  1. 先读 reactivity,能最快了解 Vue 3 的新特性;
  2. 再读 rumtime,理解组件和生命周期的实现;
  3. 如果还有时间再读 compiler,理解编译优化过程。

另外如果你想省时间,可以直接看所有 __tests__ 目录里的测试用例来了解 Vue 3 的所有功能。目前有不到 700 个测试用例。

代码结构

代码仓库中有个 packages 目录,里面是 Vue 3 的主要功能的实现,包括

  • reactivity 目录:数据响应式系统,这是一个单独的系统,可以与任何框架配合使用。
  • runtime-core 目录:与平台无关的运行时。其实现的功能有虚拟 DOM 渲染器、Vue 组件和 Vue 的各种API,我们可以利用这个 runtime 实现针对某个具体平台的高阶 runtime,比如自定义渲染器。
  • runtime-dom 目录: 针对浏览器的 runtime。其功能包括处理原生 DOM API、DOM 事件和 DOM 属性等。
  • runtime-test 目录: 一个专门为了测试而写的轻量级 runtime。由于这个 rumtime 「渲染」出的 DOM 树其实是一个 JS 对象,所以这个 runtime 可以用在所有 JS 环境里。你可以用它来测试渲染是否正确。它还可以用于序列化 DOM、触发 DOM 事件,以及记录某次更新中的 DOM 操作。
  • server-renderer 目录: 用于 SSR。尚未实现。
  • compiler-core 目录: 平台无关的编译器. 它既包含可扩展的基础功能,也包含所有平台无关的插件。
  • compiler-dom 目录: 针对浏览器而写的编译器。
  • shared 目录: 没有暴露任何 API,主要包含了一些平台无关的内部帮助方法。
  • vue 目录: 用于构建「完整构建」版本,引用了上面提到的 runtime 和 compiler。

可以看出,新的 Vue 代码仓库是模块化的。接下来我们逐一来看看每个模块暴露的 API。

@vue/runtime-core 模块

大部分 Vue 开发者应该不会用到这个模块,因为它是专门用于自定义 renderer 的。

使用方法示例:

import { createRenderer, createAppAPI } from '@vue/runtime-core'

const { render, createApp } = createRenderer({
 pathcProp,
 insert,
 remove,
 createElement,
 // ...
})

// `render` 是底层 API
// `createApp` 会产生一个 app 实例,该实例拥有全局的可配置上下文
export { render, createApp }

export * from '@vue/runtime-core'

@vue/runtime-dom 模块

这个模块是基于上面模块而写的浏览器上的 runtime,主要功能是适配了浏览器环境下节点和节点属性的增删改查。它暴露了两个重要 API:render 和 createApp,并声明了一个 ComponentPublicInstance 接口。

export { render, createApp }

// re-export everything from core
// h, Component, reactivity API, nextTick, flags & types
export * from '@vue/runtime-core'

export interface ComponentPublicInstance {
 $el: Element
}

@vue/runtime-test 模块

这个模块的主要功能是用对象来表示 DOM 树,方便测试。并且提供了很多有用的 API 方便测试:

export { render, createApp }

// convenience for one-off render validations
export function renderToString(vnode: VNode) {
 const root = nodeOps.createElement('div')
 render(vnode, root)
 return serializeInner(root)
}

export * from './triggerEvent'
export * from './serialize'
export * from './nodeOps'
export * from './jestUtils'
export * from '@vue/runtime-core'

@vue/reactivity 模块

这是一个极其重要的模块,它是一个数据响应式系统。其暴露的主要 API 有 ref(数据容器)、reactive(基于 Proxy 实现的响应式数据)、computed(计算数据)、effect(副作用) 等几部分:

export { ref, isRef, toRefs, Ref, UnwrapRef } from './ref'
export {
 reactive,
 isReactive,
 readonly,
 isReadonly,
 toRaw,
 markReadonly,
 markNonReactive
} from './reactive'
export {
 computed,
 ComputedRef,
 WritableComputedRef,
 WritableComputedOptions
} from './computed'
export {
 effect,
 stop,
 pauseTracking,
 resumeTracking,
 ITERATE_KEY,
 ReactiveEffect,
 ReactiveEffectOptions,
 DebuggerEvent
} from './effect'
export { lock, unlock } from './lock'
export { OperationTypes } from './operations'

很明显,这个模块就是 Composition API 的核心了,其中的 ref 和 reactive 应该重点掌握。

@vue/compiler-core 模块

这个编译器的暴露了 AST 和 baseCompile 相关的 API,它能把一个字符串变成一棵 AST。

export function baseCompile(
 template: string | RootNode,
 options: CompilerOptions = {}
): CodegenResult {
 // 详情略 ...
 return generate(ast, options)
}

export { parse, ParserOptions, TextModes } from './parse'
export { transform /* ... */ } from './transform'
export { generate, CodegenOptions, CodegenContext, CodegenResult} from './codegen'
export { ErrorCodes, CompilerError, createCompilerError } from './errors'
export * from './ast'

@vue/compiler-dom 模块

这个模块则基于上个模块,针对浏览器做了适配,如对 textarea 和 style 标签做了特殊处理。

@vue/server-renderer 模块

目前这个模块没有实现任何功能。

vue 模块

这个模块就是简单的引入了 runtime 和 compiler:

import { compile, CompilerOptions } from '@vue/compiler-dom'
import { registerRuntimeCompiler, RenderFunction } from '@vue/runtime-dom'

function compileToFunction(
 template: string,
 options?: CompilerOptions
): RenderFunction {
 const { code } = compile(template, {
  hoistStatic: true,
  ...options
 })
 return new Function(code)() as RenderFunction
}

registerRuntimeCompiler(compileToFunction)

export { compileToFunction as compile }
export * from '@vue/runtime-dom'

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript prototype 原型链
Mar 12 Javascript
40个有创意的jQuery图片和内容滑动及弹出插件收藏集之二
Dec 31 Javascript
JS中不为人知的五种声明Number的方式简要概述
Feb 22 Javascript
json数据处理技巧(字段带空格、增加字段、排序等等)
Jun 14 Javascript
jQuery Dom元素操作技巧
Feb 04 jQuery
jQuery实现表单动态添加与删除数据操作示例
Jul 03 jQuery
解决百度Echarts图表坐标轴越界的方法
Oct 17 Javascript
jQuery选择器之层次选择器用法实例分析
Feb 19 jQuery
详解微信小程序实现跑马灯效果(附完整代码)
Apr 29 Javascript
js实现for循环跳过undefined值示例
Jul 02 Javascript
ZK中使用JS读取客户端txt文件内容问题
Nov 07 Javascript
vue中get请求如何传递数组参数的方法示例
Nov 08 Javascript
基于JS实现父组件的请求服务过程解析
Oct 14 #Javascript
JavaScript this在函数中的指向及实例详解
Oct 14 #Javascript
vue循环数组改变点击文字的颜色
Oct 14 #Javascript
基于纯JS实现多张图片的懒加载Lazy过程解析
Oct 14 #Javascript
VUE+node(express)实现前后端分离
Oct 13 #Javascript
javascript sort()对数组中的元素进行排序详解
Oct 13 #Javascript
javaScript把其它类型转换为Number类型
Oct 13 #Javascript
You might like
php中如何防止表单的重复提交
2013/08/02 PHP
PHP 利用Mail_MimeDecode类提取邮件信息示例
2014/01/26 PHP
php计算指定目录下文件占用空间的方法
2015/03/13 PHP
PHP中trim()函数简单使用指南
2015/04/16 PHP
PHP使用pdo实现事务处理操作示例
2018/09/05 PHP
php二维数组按某个键值排序的实例讲解
2019/02/15 PHP
解密效果
2006/06/23 Javascript
计算新浪Weibo消息长度(还可以输入119字)
2013/07/02 Javascript
可兼容IE的获取及设置cookie的jquery.cookie函数方法
2013/09/02 Javascript
javascript+ajax实现产品页面加载信息
2015/07/09 Javascript
基于angular实现三级联动的生日插件
2017/05/12 Javascript
使用express搭建一个简单的查询服务器的方法
2018/02/09 Javascript
jQuery实现的页面详情展开收起功能示例
2018/06/11 jQuery
vue-cli3项目升级到vue-cli4 的方法总结
2020/03/19 Javascript
jQuery实现视频展示效果
2020/05/30 jQuery
[01:15:45]DOTA2上海特级锦标赛B组小组赛#1 Alliance VS Spirit第一局
2016/02/26 DOTA
python基于phantomjs实现导入图片
2016/05/13 Python
python实现斐波那契数列的方法示例
2017/01/12 Python
python 3利用BeautifulSoup抓取div标签的方法示例
2017/05/28 Python
python 通过麦克风录音 生成wav文件的方法
2019/01/09 Python
解决python中导入win32com.client出错的问题
2019/07/26 Python
python统计文章中单词出现次数实例
2020/02/27 Python
HTML5新增form控件和表单属性实例代码详解
2019/05/15 HTML / CSS
HTML5实现移动端点击翻牌功能
2020/10/23 HTML / CSS
CK加拿大官网:Calvin Klein加拿大
2020/03/14 全球购物
出纳担保书范文
2014/04/02 职场文书
解除财产保全担保书
2014/05/20 职场文书
2014派出所所长群众路线对照检查材料思想汇报
2014/09/18 职场文书
人民的好儿女观后感
2015/06/18 职场文书
电工生产实习心得体会
2016/01/22 职场文书
小学美术教学反思
2016/02/17 职场文书
2019年度政务公开考核工作总结模板
2019/11/11 职场文书
Java中使用Filter过滤器的方法
2021/06/28 Java/Android
MySQL 用 limit 为什么会影响性能
2021/09/15 MySQL
golang连接MySQl使用sqlx库
2022/04/14 Golang
Python matplotlib安装以及实现简单曲线的绘制
2022/04/26 Python