当初刚开始学习vue3时就买了霍春阳大佬的《Vue.js的设计与实现》,看了1/3,当时还看的迷迷糊糊,有许多地方不太懂,经过一年多的工作,在这期间学习到了很多,对底层的许多东西,也有了自己的了解,重新再次看这本书,获益匪浅,以下是笔记。
第一章 权衡的艺术
1.命令式和声明式
早年间前端框架jquery就是典型的命令式框架,命令式框架的特点:关注过程,性能好,但用户心智负担大。
vue.js则是声明式框架,而声明式与命令式框架不同,声明式框架更加关注结果,也就是说Vue.js帮我们封装了过程,那么Vue.js的内部实现是命令式的,而暴露给用户的却更加声明式。
2.性能与可维护性的权衡
权衡的艺术则是体现在性能与可维护性之间的权衡。
声明式代码的性能不优于命令式代码的性能,声明式代码会比命令式代码多出找出差异的性能消耗,毕竟vue框架本身就是封装了命令式代码才实现了面向用户的声明式。
为什么Vue.js要选择声明式的设计方案呢?声明式代码的可维护行强
在保持可维护性的同时让性能损失最小化就是Vue.js要做的,虚拟Dom就是为了最小化找出差异这一步的性能消耗而出现的。
3.虚拟Dom的性能如何?
虚拟Dom | innerHtml | |
---|---|---|
纯js运算 | 创建新的js对象+Diff | 渲染html字符串 |
Dom运算 | 必要的Dom更新 | 销毁所有旧Dom 新建所有新dom |
性能因素 | 与数据变化量相关 | 与模板大小相关 |
innerHtml | 虚拟Dom | 原生js |
---|---|---|
心智负担中等 | 心智负担小 | 心智负担大 |
近乎没啥维护性 | 可维护性强 | 可维护性差 |
性能差 | 性能不错 | 性能高 |
由此可见vue.js为什么选择虚拟Dom
4.运行时和编译时
vue.js3是一个编译时+运行时的框架,它在保持灵活性的基础上,还能通过编译手段分析用户提供的内容,从而进一步提升更新性能。
第二章 框架的设计核心要素
1.提升用户的开发体验
例如:提供用户必要的警告信息
2.控制框架代码的体积
例如:使用的rollup.js对项目进行构建,通过rollup.js插件配置预定义_DEV_常量也就是是否开发环境,生产环境的话类似警告信息这些在构建时会被移除,这样就做到了在开发环境中为用户提供友好的警告信息的同时,不会增加生产环境代码的提示等等
3.框架要做到良好的Tree-Shaking
Tree-Shaking指的就是消除那些永远不会被执行的代码,tree-Shaking同样也是rollup.js插件提供的。
Tree-Shaking是依赖ESM的静态结构,就是说模块必须是ESM(ES moudle)
4.框架应该输出怎样的构建产物
框架的构建产物应该包括可执行的JavaScript文件、CSS样式文件、模板文件、静态资源文件以及文档和示例等内容。这些构建产物可以帮助开发者使用和集成框架,构建出符合需求的Web应用程序,同时把不必要Tree-Shaking。
5.特性开关
如vue3中仍可使用选项式api的方式编写代码,但如果明确不使用选项式api,用户就可以使用*Vue_OPTIONS_API*开关关闭该特性,那么生产构建时,这部分代码就不会打包在最终资源中,从而减小体积资源。
6.错误处理
如 Vue.js提供了全局的错误捕获机制,提供了registerErrorHandler函数,用户可以使用它注册错误处理程序,然后在callWithErrorHandling函数内部捕获错误后,把错误传递给用户注册的错误处理程序。
7.良好的ts支持
老生常谈的了,不多bb了,这2页我都没看,哈哈!
第三章 vue.js的设计思路
1.虚拟DOM
vue.js是一个声明式的UI框架,那又如何去描述ui视图呢?使用js对象来描述UI的方式,就是所谓的虚拟DOM。虚拟Dom其实就是用来描述真实DOM的普通js对象。
2.渲染器
那虚拟Dom又是怎么变成真实的Dom呢?就是渲染器,渲染器的作用就是把render函数返回的虚拟dom转换成真实Dom,同时也会处理组件的数据响应式更新。
3.组件
组件是什么?组件和虚拟dom的关系?渲染器是如何渲染组件的?
- 组件就是一组DOM元素的封装
- 组件的返回值也是虚拟DOM
- 会对虚拟DOM进行遍历,并根据虚拟Dom的类型和属性创建响应的Dom元素。ui视图发生变动时,结合Diff算法完成新老节点的对比,渲染更新。
4.模板的工作原理
无论时手写虚拟Dom(渲染函数)还是使用模板,都属于声明式地描述UI,上面说了渲染器是把虚拟DOM渲染成真实DOM,哪虚拟DOM又是怎么得到的呢?那就是编译器
5.编译器
编译器的作用其实就是将模板编译未渲染函数
总结来说无论是使用模板还是直接手写渲染函数,对于一个组件来说,它要渲染的内容最终都是通过渲染函数产生的,然后渲染器再把渲染函数返回的虚拟DOM渲染未真实DOM,这就是模板的工作原理,也是Vue.js渲染页面的流程。
模板=>编译器=>render函数(return 虚拟Dom)=>渲染器=>真实Dom
6.vue.js是各个模板组成的有机整体
由上面可知,组件的实现依赖于渲染器,模板的编译依赖于编译器。在vue2中更多的是在渲染时通过diff算法完成渲染更新,这个寻找的过程需要花费力气,,如果从编译器的角度分析,编译器有能力分析动态内容,并在编译阶段把这些信息提取出来。就不需要渲染器花费大力气了。
vue3在编译器编译完动态的属性会生成一个patchFlags属性去告诉渲染器,哪些属性是动态的,省去渲染器找的工作量,也就提升了性能。