潜心修炼之精读《Vue.js设计与实现》第1️⃣章 权衡的艺术

第一章中从多个角度讲述了 Vue.js 设计时的权衡:

命令式和声明式

命令式关注过程,声明式强调结果。 书中举了一个例子: 获取一个 id 为 app 的 div 标签,将它的文本内容设置为 hello world,并给他绑定一个点击会弹出 ok 的事件。如果我们通过原生实现:

js 复制代码
const div = document.querySelector('#app');           // 获取指定 div
div.innerText = 'hello world';                        // 设置文本内容
div.addEventListener('click', () => { alert('ok') });  // 绑定点击事件

很显然这是一个命令式的操作,而在声明式中,我们直接将这一需求声明给 Vue.js,无需自己去考虑每一步如何操作DOM:

js 复制代码
<div @click="() => { alert('ok') }">hello world</div>

考虑到最终的结果是改变了DOM的,必然是执行了JavaScript代码的,所以 Vue.js 的内部实现仍然是命令式 的,只是暴露给用户的部分采用了声明式

性能与可维护性

对于上面的代码,假如我们想把文本内容修改成 "hello vue":

js 复制代码
div.innerText = 'hello vue'; // 原生命令式

<div @click="() => { alert('ok') }">hello vue</div> // Vue.js 声明式

在声明式中,框架并不知道哪些地方发生了变更,它需要找到前后的差异再对变化进行更新,而它执行更新的代码仍然是:div.innerText = 'hello vue'

  • 命令式代码的更新性能消耗 = 直接修改的性能消耗
  • 命令式代码的更新性能消耗 = 直接修改的性能消耗 + 找出差异的性能消耗

不难意识到一个结论,声明式代码的性能是不会优于命令式代码的性能的。而命令式的缺点就在于可维护性,从上面的代码也可以感受到,同样的功能 Vue.js 一行实现,而命令式需要三行;声明式的代码非常直观,利于维护。

虚拟 DOM 的性能到底如何

虚拟 DOM 就是为了最小化上面提到的找出差异的性能消耗而出现的。

书中对比了虚拟 DOM 和原生或 jQuery 开发中常用到的模板字符串配合 innerHTML 方式在更新页面时的性能:

首先我们要明确一些前提:涉及 DOM 的计算要远比 JavaScript 层面的计算性能差,有数量级的差距。Diff 的性能细究起来可能比渲染模板字符串要差,但是仍在同一个数量级。然后再来看二者在创建页面与更新页面时的性能对比:

创建页面时:

innerHTML(模板) 虚拟DOM
JavaScript 层面的计算 渲染模板 HTML 字符串 创建 JavaScript 对象(VNode)
DOM 层面的计算 新建所有 DOM 元素 新建所有 DOM 元素

更新页面时:

innerHTML(模板) 虚拟DOM
JavaScript 层面的计算 渲染模板 HTML 字符串 · 创建新的 JavaScript 对象 + Diff
DOM 层面的计算 · 销毁所有的旧 DOM · 新建所有的新 DOM · 与模板大小相关 · 必要的 DOM 更新 · 与数据变化量相关

根据我们强调过的前提,二者在创建页面时性能相近;更新页面时,Diff 可以帮助我们只更新必要的元素,而 nnerHTML 要全量更新。一旦模板字符串中的 DOM 节点过多,全量更新和必要更新的性能差距就很大了。

运行时和编译时

概念:

  • 运行时: 运行时框架是在我们将DOM的数据结构传入到渲染函数时,就可以直接渲染出真实的DOM结构元素。例如,我们可以创建一个render函数,通过给该函数传入源数据并调用,就可以得到真实的DOM结构。
  • 编译时: 在编译时框架中,我们通常使用模板语法(如Vue的单文件组件)。这需要一个编译器来解析模板代码,将模板代码编译成真实的DOM结构。
  • 运行+编译时: 这种框架既支持运行时(用户可以直接提供数据对象从而无须编译),又支持编译时(用户可以提供HTML字符串,我们将其编译为数据对象后再交给运行时处理)。

特点:

  • 运行时 的框架:它没有编译的过程,因此我们没办法分析用户提供的内容 ,但是如果加入编译步骤,可能就大不一样了,我们可以分析用户提供的内容,看看哪些内容未来可能会改变,哪些内容永远不会改变,这样我们就可以在编译的时候提取这些信息,然后将其传递给 Render 函数,Render 函数得到这些信息之后,就可以做进一步的优化了。
  • 编译时的框架:可以分析用户提供的内容。由于不需要任何运行时,而是直接编译成可执行的 JavaScript 代码,因此性能可能会更好,但是这种做法有损灵活性,即用户提供的内容必须编译后才能用。

Vue.js 3 在保留运行时的情况下,其性能甚至不输纯编译时的框架。

相关推荐
用泥种荷花15 分钟前
从 0 到 1 做一个支持 NFC 写入的小程序,需要哪些 API?
前端
90程序员32 分钟前
纯浏览器解析 APK 信息,不用服务器 | 开源了一个小工具
前端·apk
用户114818678948436 分钟前
Vosk-Browser 实现浏览器离线语音转文字
前端·javascript
江上清风山间明月40 分钟前
Vite现代化的前端构建工具详解
前端·webpack·nodejs·vite
PBitW42 分钟前
apijson 让前端自己定义接口 —— 但不推荐
前端·apijson
存在X42 分钟前
前端自动化编译Jenkins
前端·github
军军君011 小时前
数字孪生监控大屏实战模板:云数据中心展示平台
前端·javascript·vue.js·typescript·前端框架·es6·echarts
吴声子夜歌1 小时前
Vue3——使用axios实现Ajax请求
前端·javascript·ajax·axios
qq4356947011 小时前
JavaWeb05
前端·html
@PHARAOH1 小时前
WHAT - W3C WCAG 2.1 AA 无障碍标准
前端