潜心修炼之精读《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 在保留运行时的情况下,其性能甚至不输纯编译时的框架。

相关推荐
崔庆才丨静觅4 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了5 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅5 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅5 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅5 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment6 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅6 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊6 小时前
jwt介绍
前端
爱敲代码的小鱼6 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax