Appearance
第1章-权衡的艺术
1.1 命令式和声明式
从范式上来看,视图层框架通常分为命令式和声明式,它们各有优缺点
命令式
例子:
jsconst div = document.querySelector('#app') // 获取 div div.innerText = 'hello world' // 设置文本内容 div.addEventListener('click', () => { alert('ok') })
const div = document.querySelector('#app') // 获取 div div.innerText = 'hello world' // 设置文本内容 div.addEventListener('click', () => { alert('ok') })
可以看到,自然语言描述能够与代码产生一一对应的关系,代码本身描述的是“做事的过程”,这符合我们的逻辑直觉。
声明式
例子:
js<div @click="() => alert('ok')">hello world</div>
<div @click="() => alert('ok')">hello world</div>
可以看到,我们提供的是一个“结果”,至于如何实现这个“结果”,我们并不关心。所以它是一个声明式的代码。
1.2 性能与可维护性的权衡
结论:声明式代码的性能不优于命令式代码的性能。
声明式代码的更新性能消耗 = 找出差异的性能消耗 + 直接修改的性能消耗
js
div.textContent = 'hello vue3' // 直接修改
div.textContent = 'hello vue3' // 直接修改
VS
html
<!-- 之前: -->
<div @click="() => alert('ok')">hello world</div>
<!-- 之后: -->
<div @click="() => alert('ok')">hello vue3</div>
<!-- 之前: -->
<div @click="() => alert('ok')">hello world</div>
<!-- 之后: -->
<div @click="() => alert('ok')">hello vue3</div>
可以发现直接修改textContent
的性能肯定是优于声明式
的。因为声明式框架还要经过框架运行时
的过程。
1.3 虚拟 DOM 的性能到底如何
在大部分情况下,我们很难写出绝对优化的命令式代码,尤其是当应用程序的规模很大的时候,即使你写出了极致优化的代码,也一定耗费了巨大的精力,这时的投入产出比其实并不高。
innerHTML 和虚拟 DOM 在创建页面时的性能
1.4 运行时和编译时
纯运行时
不需要任何编译,直接运行代码,就是运行时。比如你使用react,但不使用jsx语法,直接手写React.createElement,这就少了编译的步骤,可以直接运行代码。
纯编译时
需要对代码编译后,才能运行,就是编译时。例如Svelte框架, 你需要按照Svelte提供的dsl语法来写代码,经过编译后才运行。
运行时编译
代码在运行的时候编译,然后执行。例如我们用vue打包后的代码
vue.global.js
。这个文件中就包含了compileTemplate
的代码。我们执行代码的过程中,还要经过编译,最后执行。编译时 + 运行时
需要先经过打包工具对你的代码进行编译。然后在运行的时候就不需要编译了,直接执行。例如vue-loader,在项目冷启动或hmr的时候进行编译。