《Vue.js 设计与实现》读书笔记(1-3章)
第 1 章、权衡的艺术
命令式 or 声明式
命令式:关注过程
声明式:关注结果
声明式直接声明想要的结果,框架帮用户封装好命令式的代码,所以在封装的过程中要做一些其他的事情来(生成要做的事情/找出差异)生成命令式的代码,优势是可维护性强,但是性能:命令式 ≥ 声明式。
框架设计要做的就是,保持可维护性,同时让性能损失更少。
虚拟 DOM
性能:innerHTML < 虚拟DOM < 原生JavaScript
心智负担/可维护性:虚拟DOM < innerHTML < 原生JavaScript
运行时和编译时
三种选择:纯运行时、运行时+编译时、纯编译时
手写vdom太麻烦,所以通过模板 or JSX 完成书写,但是这些还需要经历一次编译
Vue:运行时+编译时
Svelte: 纯编译时
第 2 章、设计框架要注意什么?
提升开发体验
用户未按要求使用时的错误提示,console
自定义 formatter
直观显示数据
控制框架代码的体积
开发环境提供良好提示,不增加生产环境体积。(通过 __DEV__
变量判断)
Tree-Shaking
使用 ESM
如果一个函数有副作用,将不会被 Tree-Shaking 删除,通过 /*#__PURE__*/
在打包工作( rollup/webpack )中声明没有副作用。
输出产物
IIFE:rollup format: 'iife'
ESM: format: 'esm'
CommonJS: format: 'cjs'
特性开关
用户关闭的特性,利用 Tree-Shaking 不打包到最终资源里。比如在 Vue3 中,对于 options API
处理错误
执行用户提供的函数时,做统一的错误处理(try...catch
),并提供给用户错误接口来处理。(可以错误上报等。)
TypeScript类型支持
第 3 章、Vue3 的设计思路
声明式的描述 UI
模板描述,或者虚拟DOM描述
渲染器
渲染器:把虚拟DOM变成真实DOM并渲染到浏览器页面。一个简单的渲染器实现:
点击查看代码
const vnode = {
tag: 'div',
props: {
onClick: () => alert('hello'),
},
children: 'click me',
};
function renderer(vnode, container) {
const el = document.createElement(vnode.tag);
for (const key in vnode.props) {
if (/^on/.test(key)) {
// on 开头是事件
el.addEventListener(
key.substr(2).toLowerCase(), // 事件名 onClick -> click
vnode.props[key] // 事件处理函数
);
}
}
// 处理 children
if (typeof vnode.children === 'string') {
el.appendChild(document.createTextNode(vnode.children));
} else if (Array.isArray(vnode.children)) {
vnode.children.forEach((child) => {
renderer(child, el);
});
}
container.appendChild(el);
}
renderer(vnode, document.body);
组件的本质
组件就是一组 DOM 元素的封装。上面的渲染器兼容组件(包括函数写法和对象写法):
点击查看代码
const MyComponent = function() {
return {
tag: 'div',
props: {
onClick: () => alert('hello'),
},
children: 'click me - MyComponent',
}
}
const MyComponent1 = {
render() {
return {
tag: 'div',
props: {
onClick: () => alert('hello'),
},
children: 'click me - MyComponent1',
}
}
}
const vnode = {
tag: MyComponent
};
function renderer(vnode, container) {
if (typeof vnode.tag === 'string') {
// 标签元素
mountElement(vnode, container);
} else if (typeof vnode.tag === 'function') {
// 函数描述组件
mountFunctionComponent(vnode, container);
} else if (typeof vnode.tag === 'object') {
// 对象描述组件
mountObjectComponent(vnode, container)
}
}
function mountElement(vnode, container) {
const el = document.createElement(vnode.tag);
for (const key in vnode.props) {
if (/^on/.test(key)) {
// on 开头是事件
el.addEventListener(
key.substr(2).toLowerCase(), // 事件名 onClick -> click
vnode.props[key] // 事件处理函数
);
}
}
// 处理 children
if (typeof vnode.children === 'string') {
el.appendChild(document.createTextNode(vnode.children));
} else if (Array.isArray(vnode.children)) {
vnode.children.forEach((child) => {
renderer(child, el);
});
}
container.appendChild(el);
}
function mountFunctionComponent(vnode, container) {
// 获取 vnode
const subtree = vnode.tag();
renderer(subtree, container);
}
function mountObjectComponent(vnode, container) {
// 获取 vnode
const subtree = vnode.tag.render();
renderer(subtree, container);
}
renderer(vnode, document.body);
模板的工作原理
编译器:模板编译为渲染函数
<div @click="handler">
click me
</div>
编译为
render() {
return h('div', { onClick: handler }, 'click me')
}
Vue 是各模块组成的有机体
模板 --[编译器]--> 渲染函数 --[渲染器]--> 真实DOM
如果在编译器中增加优化,比如静态节点的判断,就可以在渲染器减少一些工作。
《Vue.js 设计与实现》读书笔记(1-3章)的更多相关文章
- Javascript高级程序设计读书笔记(第二章)
第二章 在HTML中使用Javascript 2.1<script>元素 延迟脚本(defer = "defer")表明脚本在执行时不会影响页面的构造,脚本会被延迟到 ...
- javascript高级程序设计读书笔记-事件(一)
读书笔记,写的很乱 事件处理程序 事件处理程序分为三种: 1.html事件2. DOM0级,3,DOM2级别 没有DOM1 同样的事件 DOM0会顶掉html事件 因为他们都是属性 而 ...
- Javascript高级程序设计读书笔记(第六章)
第6章 面向对象的程序设计 6.2 创建对象 创建某个类的实例,必须使用new操作符调用构造函数会经历以下四个步骤: 创建一个新对象: 将构造函数的作用域赋给新对象: 执行构造函数中的代码: 返回新 ...
- JavaScript高级程序设计 读书笔记 第一章
JavaScript是一种专门为与网页交互而设计的脚本语言 JavaScript实现 ECMAscript---核心 DOM---文档对象模型 BOM---浏览器对象模型
- Javascript高级程序设计读书笔记(第10章 DOM)
第10章 DOM 10.1 节点层次 每个节点都有一个nodeType属性,用于表明节点的类型.任何节点类型必是下面中的一个: Node.Element_NODE(1); NODE.ATTRIBUT ...
- Javascript高级程序设计读书笔记(第三章)
第3章 基本概念 3.4 数据类型 5种简单数据类型:undefined.boolean.number.null.string. typeof操作符,能返回下列某个字符串:“undefined”.“b ...
- JavaScript高级程序设计 读书笔记 第二章
<script>元素 直接在页面中嵌入JavaSript代码或包含外部JavaSript文件. 在代码中任何地方不能出现</script>,可通过转义字符'\'解决. 在XHT ...
- javascript高级程序设计读书笔记
第2章 在html中使用javascript 一般都会把js引用文件放在</body>前面,而不是放在<head>里, 目的是最后读取js文件以提高网页载入速度. 引用js文 ...
- JavaScript高级程序设计-读书笔记(7)
第22章 高级技巧 1.高级函数 (1)安全的类型检测 在任何值上调用Object原生的toString()方法,都会返回一个[object NativeConstructorName]格式的字符串. ...
- JavaScript高级程序设计 读书笔记
第一章 JavaScript 简介 第二章 Html中使用JavaScript 第三章 基本概念 第四章 变量,作用域,内存 第五章 引用类型 第六章 面向对象 第七章 函数表达式 第八章 BOM 第 ...
随机推荐
- STM32开发环境配置记录——关于PlatformIO + VSCode + CubeMX的集成环境配置
前言 为什么配置这样的一个环境呢?鄙人受够了Keil5那个简陋的工作环境了,实在是用不下去,调试上很容易跟CubeMX的代码产生不协调导致调试--发布代码不一致造成的一系列问题.CubeIDE虽说 ...
- 【.bat】IISExpress配置通过IP访问程序
本页只记录便携运行方式脚本 详细IISExpress配置方法请看: VS的IISExpress配置通过IP访问程序 网络信息:192.168.1.45:8378 Run.bat :: run as a ...
- holiday week 1
本周进度总结: JAVA javafx以安装完毕并完成了环境配置 因处于小学期中java暂时搁置学习 自学了部分链表.多线程以及一些C/C++的知识,对部分C++库有了更进一步了解 因多线程的问题将平 ...
- 【郝斌C ST】指针 swap问题
C语言 指针 swap问题 在主函数种实现变量的交换 现在我们把这交换的行为封装进方法中 swap函数确实进行了交换,打印也是10和5了,但是下面a和b的结果还是5和10 - 形参i 和 形参j 并不 ...
- 为什么自动驾驶领域发论文都是用强化学习算法,但是实际公司里却没有一家使用强化学习算法?—— (特斯拉今年年初宣布推出实际上第一款纯端到端的自动驾驶系统,全部使用强化算法,替换掉30万行C++的rule-based代码)
为什么自动驾驶领域发论文都是用强化学习算法,但是实际公司里却没有一家使用强化学习算法?-- (特斯拉今年年初宣布推出实际上第一款纯端到端的自动驾驶系统,全部使用强化算法,替换掉原有的30万行C++的r ...
- pytorch的模型推理:TensorRT的使用
相关教程视频: TRTorch真香,一键启用TensorRT 注意,这里只做入门视频的学习Demo,并没有实际应用的用处. 图片来源:https://www.bilibili.com/video/BV ...
- 如何使用工具下载B站非会员视频(下载B站免费web视频)
最近准备从B站上下载几个web页面上的视频,但是B站的视频又没有提供相关的下载工具,于是找到了一款下载B站视频的工具( you-get ), 该工具不能下载会员版的视频,不能下载收费的视频,不过对于免 ...
- mindspore.ops.Pow()等算子不能处理float64类型的数据
原文地址: https://gitee.com/mindspore/mindspore/issues/I3ZG99 Software Environment: -- MindSpore r1.2 GP ...
- 最小二乘法的矩阵正则化改进——“岭回归”和“LASSO回归”算法
看代码过程中发现了一个很奇怪的概念,叫做"最小二乘法的矩阵正则化",这个词汇十分的陌生,虽然最小二乘法是知道的,但是用了矩阵正则化的最小二乘法是个什么东西呢? 相关代码见: 强化学 ...
- python 音频处理(2)——提取PPG特征之whisper库的使用(2.1)
提取PPG特征之--whisper库的使用(2.1) 1 安装对应的包 方法一(自用): 直接pip即可: pip install openai-whisper 成功后如下图所示 方法二: 当时用了他 ...