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

相关推荐
燃先生._.32 分钟前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖1 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235242 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240252 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar2 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人3 小时前
前端知识补充—CSS
前端·css
GISer_Jing3 小时前
2025前端面试热门题目——计算机网络篇
前端·计算机网络·面试
m0_748245523 小时前
吉利前端、AI面试
前端·面试·职场和发展
理想不理想v4 小时前
webpack最基础的配置
前端·webpack·node.js