Vue.js 设计与实现 知识点 Vol. 1 | 青训营笔记

112 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的的第20天

我将创作一些 Vue.js 学习相关的笔记。

《Vue.js设计与实现》笔记 Vol. 1

框架设计概览

权衡的艺术

命令式和声明式

命令式:

  • 更加关注过程
  • 理论上可以做到极致优化
  • 用户要承受巨大的心智负担

声明式:

  • 更加关注结果
  • 性能上有一定的牺牲
  • 能够有效减轻用户的心智负担

性能与可维护性的权衡

声明式代码的性能不优于命令式代码的性能,因为声明式代码会比命令式代码多处找出差异的性能消耗。

框架本身就是封装了命令式代码才实现了面向用户的声明式。

Vue.js 选择声明式的设计方案的原因:声明式代码的可维护性更强

框架设计者要做的是:在保持可维护性的同时让性能损失最小化

虚拟 DOM 的性能

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

虚拟 DOM 的意义在于使找出差异的性能消耗最小化

更新页面时的性能对比:

  • innerHTML(模板)

    • 心智负担中等
    • 性能差
  • 虚拟 DOM

    • 心智负担小
    • 可维护性强
    • 性能不错
  • 原生 JavaScript

    • 心智负担大
    • 可维护性差
    • 性能高

运行时和编译时

纯运行时框架

树型结构的数据对象:

const obj = {
  tag: 'div',
  children: [
    { tag: 'span', children: 'hello world' }
  ]
}

Render 函数:

function Render(obj, root) {
  const el = document.createElement(obj.tag)
  if (typeof obj.children === 'string') {
    const text = document.createTextNode(obj.children)
    el.appendChild(text)
  } else if (obj.children) {
    // array,递归调用 Render,使用 el 作为 root 参数
    obj.children.forEach((child) => Render(child, el))
  }
​
  // 将元素添加到 root
  root.appendChild(el)
}

使用方法:

const obj = {
  tag: 'div',
  children: [
    { tag: 'span', children: 'hello world' }
  ]
}
// 渲染到 body 下
Render(obj, document.body)
编译时 + 运行时框架

编写一个 Compiler 函数

用户分别调用 Compiler 函数和 Render 函数:

const html = `
<div>
  <span>hello world</span>
</div>
`
// 调用 Compiler 编译得到树型结构的数据对象
const obj = Compiler(html)
// 再调用 Render 进行渲染
Render(obj, document.body)
纯编译时框架

只需要 Compiler 函数,将 HTML 字符串编译为命令式代码

const div = document.createElement('div')
const span = document.createElement('span')
span.innerText = 'hello world'
div.appendChild(span)
document.body.appendChild(div)
总结

纯运行时的框架没有编译的过程,因而不能分析用户提供的内容;加入编译步骤,可以分析用户提供的内容,看看哪些内容未来可能改变,哪些内容永远不会改变,这样就可以在编译时提取这些信息,然后将其传给 Render 函数,Render 函数得到这些信息之后,可以做进一步的优化;纯编译时的框架直接将用户提供的内容编译成可执行的 JavaScript 代码,因而性能可能会更好,但有损灵活性,因为内容必须编译后才能用。

Svelte 是纯编译时的框架。

Vue.js 3 是一个编译时 + 运行时的框架,它在保持灵活性的基础上,还能通过编译手段分析用户提供的内容,从而进一步提升更行性能。

引用参考

霍春阳. Vue.js设计与实现[M]. 1. 北京:人民邮电出版社, 2022.