自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(20)
  • 收藏
  • 关注

原创 【手写简易版 vue3】究极长文详细讲解如何实现一个简易版 vue3

介绍一下 beggar-vue笔者自己写了一个 vue3 的简易版实现,非常简易,没有阅读难度,起名 beggar-vue,意思不是 “乞丐版 vue”,而是 “乞丐看了都可怜的 vue”。虽然实现很粗糙,但实现原理方面基本完全贴合源码,少量不同的地方都会做出标注和提醒,源码传送门在这里 beggar-vue,以下是一些参考信息References:vue-next: vue3 源码,很值得看vue-design: 一个大佬,vue 贡献者写的剖析 vue 设计原理的博客,很值得看mini-vu

2021-11-23 13:29:49 1327

原创 【手写简易版 vue3】总结

本篇总结一下整个 beggar-vue 的实现,会有些乱,但都是干货reactivityvue-next/packages/reactivity/src响应式模块中我们实现了 reactive、effect、ref、computed,其中最核心的是 effectreactivereactive 我们做了简化,没有进行容错处理和特例处理,也因此整体结构非常清晰简单,通过 Proxy 代理 target 目标对象的存取操作,在其中进行依赖收集 track 以及触发更新 triggereffect

2021-11-23 13:21:31 346

原创 编译模块7: compile 实现

源码位置:vue-next/packages/compile-core/src/compile.ts最后的最后就是整个模块的主入口了,只要把之前的模块整合起来即可写一下这里直接给出代码,不过多赘述了// 插件预设function getBaseTransformPreset() { return [ [transformElement, transformText], { on: transformOn, bind: transformBind,.

2021-11-23 13:21:20 281

原创 编译模块6: codegen 实现

源码位置:vue-next/packages/compile-core/src/codegen.ts上文实现了 transform,现在就进入整个 compile 最后的代码生成 codegen 环节了,个人感觉和前面的 transform 比起来,codegen 真的非常简单,源码位置在这里说在开头我的实现和源码实现区别蛮大的,因为源码中考虑了各种 helper、cache、hoist 之类的,而这些我都没实现。经过 transform 之后,AST 上的 codegenNode 节点上挂载的.

2021-11-23 13:21:04 303

原创 编译模块5: directiveTransforms 实现

源码位置:vue-next/packages/compile-core/src/transforms/vOn.tsvue-next/packages/compile-core/src/transforms/vBind.ts到这里 transform 模块其实已经基本实现了,不过还需要专门再处理一下 v-on 和 v-bind,也以此作为一个简单的例子看看指令编译都会做些什么解释一下directiveTransforms 也是一类 transform plugin 转换插件,其中包括一些 tra.

2021-11-23 13:20:55 307

原创 编译模块4: transform 实现

源码位置:vue-next/packages/compile-core/src/transform.ts通过 parse 已经生成了一棵 AST,已经可以直接用这棵 AST 来生成目标代码,但是在前置知识中也有提到,并不是为了生成 AST 而生成 AST,实际上我们可以很方便的对 AST 进行修改,以实现一些其他的需求,这里的 transform 就是做这个的讲在开头整个 transform 的过程非常复杂,而最关键的是整个 transform 模块内聚程度很高,变量彼此联系非常紧密,难以彻底简.

2021-11-23 13:20:44 729

原创 编译模块3: parse 实现

源码位置:vue-next/packages/compile-core/src/parse.ts终于是可以开始写了,实际上,因为偷了大懒,parse 并不复杂,也不会很难理解,个人感觉更多的还是流程控制分析一下模板字符串实际上是一个长长的字符串,这意味着我们没法直接从结构上分析出标签的嵌套情况,这一点非常关键,因为嵌套标签,嵌套内容是非常非常常见的操作,因此在处理上需要注意,不过转念一想,其实需要递归调用 parseChildren 的只有一种情况,也就是标签中嵌套标签的情况其实这里本来会是一.

2021-11-23 13:20:33 190

原创 编译模块2: parse 准备

源码位置:vue-next/packages/compile-core/src/parse.ts经过上文的铺垫,应该都对编译的过程以及 AST 的作用有了一定的认识,由于 parse 函数需要做的准备工作比较多,因此再分多一篇用来铺垫,下一篇就是正式实现了解释一下直接开一手上帝视角,照着源码的思路来进行解释parse 做的事情简单来说就是将模板字符串中有用的信息以各种方式提取出来,并形成一个个节点,最终构建成一棵 AST。一些准备工作以下是实现 parse 前需要做的准备,以及一些会遇到的.

2021-11-23 13:20:23 186

原创 编译模块1: 一些前置知识

上回说到,我们已经完成了响应式模块 reactivity 以及运行时模块 runtime,而在 vue 的日常使用中还有一个必不可少的功能就是模板语法,虽说可以写 jsx,但是不管是 template 模板语法还是 jsx 最终其实都会被编译成 render 和 h,而且还有大量的指令需要处理,如 v-if、v-on 等,这些都是在编译模块 compiler 中实现的,接下来就来完成编译模块凑齐最后一块拼图一轮快问快答Q: 为什么需要编译?A: 上面说了啊Q: 怎么编译?A: 这其实涉及到编译原理

2021-11-23 13:20:12 234

原创 渲染模块7: createApp 实现

源码位置:vue-next/packages/runtime-core/src/apiCreateApp.ts177 行害这个真的很简单,就把之前写过的整合起来就行看一下长啥样还是不看了,因为真的就太熟了直接写吧createApp 需要接收根组件对象 rootComponent,返回一个 App 对象,这个 rootComponent 接口大概长这样// vue-next/packages/runtime-core/src/componentOptions.ts// 108 行exp.

2021-11-23 13:19:56 273

原创 渲染模块6: 调度机制实现

源码位置:vue-next/packages/runtime-core/src/scheduler.ts其实本文中的调度机制,即 scheduler,是为了解决组件渲染时的一个渲染任务的调度问题,或者说调用时机的问题,属于是很典型的 “可以没有,但有了会更好”,但是考虑到有 nextTick 这么一个很好用的 API,且实现起来非常简单,因此顺带实现一下为什么要调度在前面实现的 component 的更新方法 instance.update 存在一个问题,就是 setup 中每一次 trigge.

2021-11-22 16:19:53 418

原创 渲染模块5: 组件渲染实现

源码位置:vue-next/packages/runtime-core/src/component.ts本文只实现了 Composition API,没有实现 Options API随着前端业务越来越复杂,也就自然而然的出现了现代化的需求,如模块化、组件化、自动化、规范化,前文的 render 和 patch 都留好了坑,本文主要来实现组件的渲染用用看根据官网文档,定义如下全局组件(省略部分无关代码)app.component('my-comp', { props: ['classN.

2021-11-22 16:19:43 646

原创 渲染模块4: diff 算法实现

正如上篇所说,vue3 的 diff 算法很有意思,性能也很好,但我指的不是前面那篇 patch,而是本篇的 diff 核心算法,源码中具体名为 patchKeyedChildren以下的 diff 算法 均指 patchKeyedChildren 的实现源码位置在'vue-next\packages\runtime-core\src\renderer.ts' 中的第 1762 行以下所有图片中,c1 为旧的子节点,c2 为新的子节点,且上为 c1,下为 c2解释一下diff 算法非常重

2021-11-22 16:19:34 334

原创 渲染模块3: patch 实现

源码位置:vue-next/packages/runtime-core/src/renderer.ts在我写到这行时(2021-10-30 22:44),vue(v3.2.1)还是三大框架(angular、react、vue)中跑 js web frameworks benchmark 最快的,抛开性能不谈,个人认为 vue3 的 diff 算法还是挺有意思的,而本文实现的是广义上的 diff 算法——patch,而由于追求精简,本文部分实现与源码有一定出入,但基本原理一致,可以放心参考介绍一下.

2021-11-22 16:19:22 354

原创 渲染模块2: render 实现

源码位置:vue-next/packages/runtime-core/src/renderer.ts结合上篇讲到的前置知识,本篇介绍 render 方法的实现,为了便于理解,仅保留核心部分,下文中 VNode 对象即是 虚拟 dom 对象作为参考,暂时只实现元素节点与文本节点,关于 patch 和 diff 以及 component 的渲染后续专门介绍分析一下根据文档以及源码来看,vue 中使用 h 函数和 render 函数来进行渲染,组合起来如下所示render() { ret.

2021-11-22 16:19:11 453

原创 渲染模块1: vnode & render 前置知识

在正式介绍渲染模块前,一些前置知识需要先解释一下虚拟 dom众所周知,vue 中运用了虚拟 dom 技术来提高性能,不过为什么虚拟 dom 是什么,为什么能提高性能呢,虚拟 dom 是最diao的么虚拟 dom 技术简而言之指的是先将需要渲染的 dom 节点在内存中创建好,再通过渲染函数一次性渲染到页面中。我们在 js 中进行的每一次 dom 操作都会引起页面回流或者重绘,大量的 dom 操作可能最终导致页面卡顿或白屏的情况。虽然目前大部分浏览器都有进行优化,维护一个操作队列,将所有会导致回流或者重

2021-11-22 16:18:56 356

原创 响应式模块4: computed 实现

本文对应源码位置vue-next/packages/reactivity/src/computed.ts26 行做完前面那些,轮也该轮到 computed 了,computed 和前面的 reactive、ref 其实非常像,但是适用场景不同,原理方面也是非常非常像,先按照前面 ref 的思路写一个出来看看照 ref 画 computed按照源码中的实现,computed 实际上是 ComputedRefImpl 的实例对象,那么就可以按照前面的 ref 的实现照葫芦画瓢,如下const c.

2021-11-22 16:18:37 924

原创 响应式模块3: ref 实现

本文对应源码位置vue-next/packages/reactivity/src/ref.ts91 行ref 也是响应式数据的一种,类似于 reactive,不过通常用 ref 封装简单数据,如 Number、String、Boolean等,用 reactive 只能封装对象,如 Object、Array等。而查阅源码可以看到 ref 实际上是 RefImpl 的实例对象,因此也就很好实现了逆向分析一下依然是惯用的自顶向下开始分析,使用 ref 封装一个简单数据const a = ref(0.

2021-11-22 16:17:45 606

原创 响应式模块2: effect 实现

本文对应源码位置vue-next/packages/reactivity/src/effect.ts53 行前置知识vue3 源码中使用了 WeakMap 来储存响应式对象与依赖的对应关系,而使用 WeakMap 个人觉得完全是出于性能考虑,因此可以使用 Map 进行代替。WeakMap 的键值必须是对象,我认为这也直接促成 reactive 在日常使用中只用来封装对象数据,这点与 ref 不同(后续实现)写来看看可以自顶向下进行分析,先看结果,实现雏形,之后慢慢完善细节,如下所示cons.

2021-11-22 16:17:22 682

原创 响应式模块1: reactive 实现

本文对应源码位置vue-next/packages/reactivity/src/reactive.ts181 行个人对响应式数据的理解为,数据更新以及数据获取时能够以某种方式主动让使用此数据的代码做出反应,简而言之就是在数据更新以及数据获取时能够执行别的操作,回归到 vue3 当中则是,数据更新时主动通过 trigger 方法触发依赖函数,获取数据时主动通过 track 方法将此依赖函数保存下来。前置知识响应式的核心原理通过 Proxy 和 Reflect 实现,以下内容来自MDNProx.

2021-11-22 16:17:03 501

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除