第一章:权衡的艺术
在这一章中,开头的一句话,描述了框架设计的精髓,这句话也是尤雨溪在多个开发者大会中经常提到的,那就是:框架的设计,本身就是一种权衡的艺术。
在本章中,我们首先讨论了命令式和声明式这两种范式的差异,其中命令式更加关注过程,而声明式更加关注结果。命令式理论上可以做到极致优化,但是用户要承受巨大的心智负担;而声明式能够有效减轻用户的心智负担,但是性能上有一定的牺牲,框架设计者要想办法尽量使性能损耗最小化。
接着讨论了虚拟DOM
的性能,并给出了一个公式:声明式的更新性能消耗 = 找出差异的性能消耗 + 直接修改的性能消耗。虚拟DOM
的意义就在于使找出差异的性能消耗最小化。对比虚拟DOM
、原生JavaScript
、innerHTML
三者操作页面的性能。发现与页面大小、变更部分的大小都有关系,除此之外,还与是创建页面还是更新页面也有关系。最后发现虚拟DOM
是个不错的选择。
最后,介绍了运行时、编译时的相关知识,了解纯运行时、纯编译时以及两者都支持的框架各有什么特点,并总结出Vue.js3是一个编译时+运行时的框架,它在保持灵活性的基础上,还能通过编译手段分析用户提供的内容,从而进一步提升性能。
在这一章中,书中分别从三个方面来去分析了所谓权衡的艺术,到底是什么意思。
命令式和声明式
所谓命令式指的就是:关注过程的范式。而声明式指的就是:关注结果的范式。
张三的妈妈,让张三去买酱油。
那么对于张三而言,他就需要:拿钱、出门、下楼、进超市、拿酱油、付钱、回家。
而对于张三的妈妈来说,她完全不需要关心张三做了什么,只需要对张三说一声就可以了。
那么在这个例子中,张三就是一个典型的命令式,他需要完成整件事情的所有过程。
而张三的妈妈,就是典型的声明式,她不关心过程只关心结果。
那么这里大家来想一下,vue
是声明式的?还是命令式的?
对于 vue
而言,它的内部实现一定是 命令式 的,而我们在使用 vue
的时候,则是通过 声明式 来使用的。
也就是说: vue 封装了命令式的过程,对外暴露出了声明式的结果
性能与可维护性的权衡
在明确好了命令式和声明式的概念之后。接下来咱们来看下从 性能 层面,vue
所体现出来的一种权衡的方式。
针对于性能的分析,主要从两个方面去说。
首先第一个方面:大家觉得 是命令式的性能更强,还是声明式的性能更强呢?
答案是:命令式的性能 > 声明式的性能。
其实原因非常简单,对于 命令式 的代码而言,它直接通过 原生的 JavaScript
进行实现,这是最简单的代码,没有比这个更简单的了,我们把它的性能比作1
。
而声明式,无论内部做了什么,它想要实现同样的功能,内部必然要实现同样的命令式代码。所以它的性能消耗一定是 1 + N
的。
那么既然如此,vue
为什么还要对外暴露出声明式的接口呢?
这其实是因为:声明式的可维护性,要远远大于命令式的可维护性。
命令式代码:
1 | const div = document.querySelector('#app') |
声明式代码:
1 | <div @click="() => alert('ok')">hello world</div> |
从这两段代码(声明式和命令式代码)中就可以发现,声明式代码比命令式代码要简单的多。
越简单的代码,可维护性就越强。
当性能与可维护性产生冲突的时候,那么舍鱼而取熊掌者也。(注意:在vue
的性能优化之下,它并不会比纯命令式的性能差太多)
而这样的一种权衡,在template
模板中,更是体现的淋漓尽致。
在前端领域,想要使用JavaScript
修改html
的方式,主要有三种:原生JavaScript
、innerHTML
、虚拟DOM
。
很多人认为虚拟DOM
的性能是最高的,其实不然。我们来看一下对比:
心智负担:虚拟DOM
< innerHTML
< 原生JavaScript
性能:innerHTML
< 虚拟DOM
< 原生JavaScript
可维护性:原生JavaScript
< innerHTML
< 虚拟DOM
从这个对比我们可以发现,虚拟 DOM
的性能,并不是最高的。
但是它的 心智负担(书写难度)最小, 从而带来了 可维护性最高。所以哪怕它的性能并不是最高的。vue
依然选择了 虚拟 DOM
来进行了渲染层的构建。
这个也是一种性能与可维护性的权衡。
运行时和编译时
第一章的最后一部分,主要讲解的就是 运行时和编译时。
这两个名词,各位小伙伴在日常开发中,应该是经常听到的。
它们两个都是框架设计的一种方式,可单独出现,也可组合使用。
那么下面咱们就分别来介绍一下它们。
首先是 运行时:runtime
。
它指的是利用render函数,直接把
虚拟DOM
转化为真实DOM
元素的一种方式。 在整个过程中,不包含编译的过程,所以无法分析用户提供的内容。
其次是编译时:compiler
:
它指的是:直接把
template
模板中的内容,转化为真实DOM
元素。因为存在编译的过程,所以可以分析用户提供的内容。同时,没有运行时理论上性能会更好。目前该方式,有具体的实现库,那就是现在也非常火的Svelte
。但是这里要注意的是,它的真实性能,没有办法达到理论数据。
最后是运行时 + 编译时:
它的过程被分为两步:
1.先把template
模板转化为render函数。也就是编译时
2.再利用render函数,把虚拟DOM
转化为真实DOM
.也就是运行时
两者的结合,可以在编译时,分析用户提供的内容,在运行时,提供足够的灵活性
这也是vue
的主要实现方式