《Vue.js设计与实现》笔记 第1章:权衡的艺术

Vue.js设计与实现 第一章:权衡的艺术

本章导读

Vue.js 并不是单纯追求性能最强或功能最多的框架,而是在多个目标之间寻找最佳平衡点。

Vue 的设计核心思想:

框架设计本质上是一门权衡(Trade-off)的艺术。

主要权衡:

  • 声明式 vs 命令式
  • 性能 vs 开发效率
  • 运行时 vs 编译时
  • 灵活性 vs 可维护性

一、命令式与声明式

命令式(Imperative)

命令式编程关注:

如何做(How)

例如:

const div = document.createElement('div')
div.textContent = 'Hello Vue'
div.id = 'app'
document.body.appendChild(div)

开发者需要一步一步描述:

  1. 创建元素
  2. 设置内容
  3. 设置属性
  4. 插入页面

特点

优点 缺点
灵活度高 代码量大
性能可控 可维护性差
能做任何复杂操作 开发效率低

声明式(Declarative)

声明式编程关注:

做什么(What)

例如:

<div id="app">Hello Vue</div>

或者:

<template>
  <div id="app">Hello Vue</div>
</template>

开发者只描述最终结果:

我要一个 div
内容为 Hello Vue
id 为 app

至于如何创建、更新 DOM,由框架负责。

特点

优点 缺点
可读性高 灵活性略低
开发效率高 存在框架开销
易维护 性能不如极致手写优化

为什么 Vue 采用声明式?

例如:

<div>{{ title }}</div>

开发者只关心:

title = 'Vue3'

而不需要关心:

  • DOM如何创建
  • DOM如何更新
  • 哪些节点发生变化

这些工作由 Vue 自动完成。

因此:

Vue 用少量性能损失
换取巨大开发效率提升

二、性能与可维护性的权衡

原生 JavaScript 性能最高

例如:

const div = document.createElement('div')
div.textContent = 'Hello'

因为:

  • 没有框架
  • 没有虚拟DOM
  • 没有运行时分析

执行路径最短。


为什么还需要框架?

因为大型项目中需要解决:

  • 状态管理
  • DOM更新
  • 组件通信
  • 生命周期管理
  • 路由管理

如果全部手写:

性能高
开发痛苦
维护困难

框架存在的意义

框架帮助开发者:

  • 管理状态
  • 管理视图
  • 管理组件
  • 管理更新流程

因此:

牺牲部分运行性能
换取更高开发效率和可维护性

三、虚拟DOM(Virtual DOM)

什么是虚拟DOM

虚拟DOM本质上是:

使用 JavaScript 对象描述真实 DOM。

例如:

const vnode = {
  tag: 'div',
  props: {
    id: 'app'
  },
  children: 'Hello Vue'
}

这里的 vnode 就是虚拟节点(VNode)。


为什么需要虚拟DOM?

直接操作 DOM 成本较高。

例如:

DOM操作
↓
触发重排(Reflow)
↓
触发重绘(Repaint)
↓
性能开销

Vue 通过虚拟DOM进行优化:

新VNode
    ↓
Diff比较
    ↓
找出变化
    ↓
更新真实DOM

虚拟DOM的优势

1. 跨平台能力

同一套 VNode 可以渲染到:

  • 浏览器 DOM
  • 服务端 HTML(SSR)
  • 小程序
  • Native

2. 更好的开发体验

开发者只需要:

<div>{{ count }}</div>

更新数据:

count++

Vue 自动更新视图。


3. 更新优化

通过 Diff 算法:

只更新变化部分

避免全量重建 DOM。


虚拟DOM的缺点

额外开销:

  • 创建 VNode
  • Diff 比较
  • 内存占用

因此:

理论性能:

手写优化DOM
    >
虚拟DOM
    >
完全重建DOM

四、运行时与编译时

运行时(Runtime)

运行时框架需要在浏览器中执行:

h('div', 'Hello Vue')

生成 VNode。

典型代表:

  • Vue 2
  • React

编译时(Compile Time)

开发者编写:

<div>Hello Vue</div>

编译器转换为:

render() {
  return h('div', 'Hello Vue')
}

编译器的作用

将:

Template

转换成:

Render Function

整体流程:

Template
   ↓
Compiler
   ↓
Render Function
   ↓
VNode
   ↓
DOM

五、Vue3为什么采用运行时+编译时

Vue3采用:

Runtime + Compiler

同时拥有两者优点。


运行时优势

灵活。

例如:

render() {
  return h(...)
}

可以动态生成任意界面。


编译时优势

编译阶段提前分析模板。

例如:

<div>
  <span>静态内容</span>
  <p>{{ msg }}</p>
</div>

编译器知道:

span 永远不会变
p 会变化

更新时:

只更新 p

无需全量 Diff。


六、Vue3编译优化

这是 Vue3 性能提升的重要来源。


1. Patch Flag(补丁标记)

编译器会标记:

哪些节点可能变化

例如:

<div>{{ msg }}</div>

编译后:

createElementVNode(
  'div',
  null,
  msg,
  PatchFlags.TEXT
)

其中:

PatchFlags.TEXT

表示:

只有文本内容会变化

更新时无需完整 Diff。


2. 静态提升(Static Hoist)

例如:

<div>
  <span>静态内容</span>
  <p>{{ msg }}</p>
</div>

编译器会将:

<span>静态内容</span>

提升到渲染函数外部。

只创建一次。

避免重复创建。


3. Block Tree

Vue3 引入:

Block Tree

用于记录:

动态节点集合

更新时:

只遍历动态节点

而不是:

遍历整棵VNode树

进一步减少 Diff 成本。


七、Vue设计目标

Vue 的设计目标可以总结为三点:

1. 易用性

例如:

<template>
  <div>{{ msg }}</div>
</template>

学习成本低。

开发效率高。


2. 高性能

通过:

  • 虚拟DOM
  • Patch Flag
  • 静态提升
  • Block Tree
  • 编译优化

提升运行效率。


3. 可维护性

通过:

  • 组件化
  • 响应式系统
  • 声明式开发

降低项目复杂度。


高频面试题

什么是声明式编程?

只描述结果,不描述实现过程。

例如:

<div>{{ msg }}</div>

Vue为什么采用声明式设计?

原因:

  • 开发效率高
  • 可维护性好
  • 更符合组件化思想

什么是虚拟DOM?

使用 JavaScript 对象描述真实 DOM。


虚拟DOM一定比原生DOM快吗?

不一定。

性能关系:

手写优化DOM
    >
虚拟DOM
    >
完全重建DOM

Vue3为什么比Vue2快?

主要原因:

  • Patch Flag
  • 静态提升
  • Block Tree
  • 编译优化

减少运行时 Diff 成本。


Vue3为什么同时拥有运行时和编译时?

因为:

运行时 → 灵活
编译时 → 高性能

两者结合能够获得更好的综合表现。


第一章核心知识图谱

Vue设计思想

├── 权衡(Trade-off)
│
├── 命令式 VS 声明式
│      └── Vue选择声明式
│
├── 性能 VS 开发效率
│      └── Vue选择平衡
│
├── 虚拟DOM
│      ├── VNode
│      ├── Diff
│      └── 跨平台
│
├── Runtime
│
├── Compiler
│
└── Vue3优化
       ├── Patch Flag
       ├── Static Hoist
       └── Block Tree

本章总结

Vue 的设计本质是:

权衡的艺术(Trade-off)。

Vue3 的核心架构:

Template
   ↓
Compiler
   ↓
Render Function
   ↓
VNode
   ↓
Diff
   ↓
DOM更新

性能优化来源:

Compiler
├── Patch Flag
├── Static Hoist
└── Block Tree

最终实现:

  • 高性能
  • 高开发效率
  • 高可维护性

这一章的内容是理解整本《Vue.js设计与实现》的理论基础,也是后续学习响应式系统、渲染器和编译器源码的核心前置知识。

posted @ 2025-01-03 10:39  Li_pk  阅读(5)  评论(0)    收藏  举报