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 相关文章推荐
用JS写的一个TableView控件代码
Jan 23 Javascript
JavaScript高级程序设计(第3版)学习笔记7 js函数(上)
Oct 11 Javascript
JavaScript 函数惰性载入的实现及其优点介绍
Aug 12 Javascript
jquery链式操作的正确使用方法
Jan 06 Javascript
Jquery修改页面标题title其它JS失效的解决方法
Oct 31 Javascript
JavaScript插件化开发教程(五)
Feb 01 Javascript
js实现Select下拉框具有输入功能的方法
Feb 06 Javascript
jQuery实现的事件绑定功能基本示例
Oct 11 jQuery
vue左右侧联动滚动的实现代码
Jun 06 Javascript
JavaScript实现指定数量的并发限制的示例代码
Mar 10 Javascript
在vue中封装的弹窗组件使用队列模式实现方法
Jul 23 Javascript
Vue Element校验validate的实例
Sep 21 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闭包(Closure)使用详解
2013/05/02 PHP
PHP 验证码不显示只有一个小红叉的解决方法
2013/09/30 PHP
Symfony2函数用法实例分析
2016/03/18 PHP
表单项的name命名为submit、reset引起的问题
2007/12/22 Javascript
javascript options属性集合操作代码
2009/12/28 Javascript
jQuery下扩展插件和拓展函数的写法(匿名函数使用的典型例子)
2010/10/20 Javascript
javascript来定义类的规范小结
2010/11/19 Javascript
几种延迟加载JS代码的方法加快网页的访问速度
2013/10/12 Javascript
js常用自定义公共函数汇总
2014/01/15 Javascript
JavaScript中的函数声明和函数表达式区别浅析
2015/03/27 Javascript
JavaScript实现简单图片翻转的方法
2015/04/17 Javascript
JS运动相关知识点小结(附弹性运动示例)
2016/01/08 Javascript
jQuery选择器及jquery案例详解(必看)
2016/05/20 Javascript
Jquery组件easyUi实现手风琴(折叠面板)示例
2016/08/23 Javascript
JS中split()用法(将字符串按指定符号分割成数组)
2016/10/24 Javascript
详解Angular CLI + Electron 开发环境搭建
2017/07/20 Javascript
jQuery DOM节点的遍历方法小结
2017/08/15 jQuery
vue2.0 实现导航守卫的具体用法(路由守卫)
2018/05/17 Javascript
vue slots 组件的组合/分发实例
2018/09/06 Javascript
基于vue实现移动端圆形旋钮插件效果
2018/11/28 Javascript
node.js 微信开发之定时获取access_token
2020/02/07 Javascript
Python 获取新浪微博的最新公共微博实例分享
2014/07/03 Python
解决python大批量读写.doc文件的问题
2018/05/08 Python
python计算阶乘和的方法(1!+2!+3!+...+n!)
2019/02/01 Python
python multiprocessing模块用法及原理介绍
2019/08/20 Python
PyTorch中permute的用法详解
2019/12/30 Python
Python tempfile模块生成临时文件和临时目录
2020/09/30 Python
澳大利高级泳装品牌:Bondi Born
2018/05/23 全球购物
行政前台岗位职责
2013/12/04 职场文书
认识深刻的检讨书
2014/02/16 职场文书
预备党员2014全国两会学习心得体会
2014/03/10 职场文书
职务任命书范本
2014/06/05 职场文书
初中生庆国庆演讲稿范文2014
2014/09/25 职场文书
2015年幼儿园保育工作总结
2015/05/12 职场文书
golang中字符串MD5生成方式总结
2021/07/04 Golang
一篇文章弄懂Python中的内建函数
2021/08/07 Python