🚀 进阶篇¶
在「基础语法」之上,深入框架设计思想与底层机制。内容结合 ECMA-262、MDN 与各框架官方文档。
1. 组合式 API vs Options API vs React Hooks¶
核心问题:如何复用与组织逻辑。
- Vue2 Options API:逻辑按选项(data/methods/computed)拆分,复用靠
mixins(易命名冲突、来源不清晰)。 - Vue3 组合式 API:用
setup+ 组合函数(composable)按"功能"聚合逻辑,类型推导好。 - React Hooks:函数组件内用
useState/useEffect/自定义 Hook复用逻辑,规则是"调用顺序稳定"。
// useCounter.js
import { ref, computed } from 'vue'
export function useCounter(init = 0) {
const count = ref(init)
const double = computed(() => count.value * 2)
const inc = () => count.value++
return { count, double, inc }
}
// useCounter.js
import { useState, useMemo } from 'react'
export function useCounter(init = 0) {
const [count, setCount] = useState(init)
const double = useMemo(() => count * 2, [count])
const inc = () => setCount(c => c + 1)
return { count, double, inc }
}
// 逻辑复用靠 mixins,易命名冲突
export default {
data() { return { count: 0 } },
computed: { double() { return this.count * 2 } },
methods: { inc() { this.count++ } }
}
可运行 Demo:逻辑复用(Vue 3 composable)
2. 渲染机制、虚拟 DOM 与 Diff¶
概念:框架不直接操作真实 DOM,而是维护一棵 虚拟 DOM(JS 对象树)。状态变化后生成新树,与旧树做 Diff,仅把最小差异 Patch 到真实 DOM,从而提升性能。
状态变更
→
生成虚拟 DOM
→
Diff 新旧树
→
计算最小补丁
→
更新真实 DOM
→
视图更新
// 编译产物类似:
// _createElementVNode('div', { onClick: inc }, ctx.count)
// 运行时通过 patch 比对 vnode,更新变化的节点
// 状态变更触发重新渲染,Fiber 架构增量比对
function App() {
const [count, setCount] = useState(0)
return <button onClick={() => setCount(c => c + 1)}>{count}</button>
}
key 的作用
列表渲染务必给每项稳定 key。Diff 时框架用 key 判断"是同一条还是新的一条",避免错位更新。index 作为 key 在增删/排序时会导致状态错乱。
3. 性能优化¶
- shallowRef / shallowReactive:跳过深层响应式
- v-memo:缓存子树,避免无效重渲染
- defineAsyncComponent:路由级组件懒加载
- 派生值用 computed 缓存
- 大列表用虚拟滚动(vue-virtual-scroller)
- React.memo:包裹组件,避免父组件渲染导致子组件无谓渲染
- useMemo / useCallback:缓存耗时计算与函数引用
- 列表使用稳定 key
- 代码分割:React.lazy + Suspense
- 大列表用虚拟滚动(react-window)
4. TypeScript 深入¶
type User = { id: number; name: string; age?: number }
type PartialUser = Partial<User> // 全部可选
type PickName = Pick<User, 'id' | 'name'> // 挑选字段
type ReadonlyUser = Readonly<User> // 全部只读
type Awaited<T> = T extends Promise<infer U> ? U : T
// Awaited<Promise<string>> => string
function identity<T>(v: T): T { return v }
// 实战:API 响应封装
type ApiRes<T> = { code: number; data: T; msg: string }
5. SSR / SSG¶
概念:服务端渲染(SSR)在服务器生成 HTML 直出,利于首屏与 SEO;静态站点生成(SSG)在构建时预渲染为静态文件。
// app/page.tsx —— 服务端组件默认在服务器运行
export default async function Page() {
const res = await fetch('https://api.example.com/data')
const data = await res.json()
return <main>{data.title}</main>
}
// server/api/hello.ts
export default defineEventHandler(() => ({ message: 'SSR 数据' }))
// 页面组件中:const { data } = await useFetch('/api/hello')
SSR 注意事项
- 服务端没有
window/document,访问浏览器 API 需在onMounted/useEffect或客户端守卫中。 - 注意"水合(hydration)"不匹配:服务端与客户端的首屏 HTML 必须一致。
6. 踩坑(注意事项)¶
常见坑
- Vue3
reactive对象整体替换(state = {...})会丢失响应性,应改属性或用ref。 - React 在
useEffect依赖数组里遗漏依赖,导致闭包拿到旧值(使用eslint-plugin-react-hooks校验)。 - Hooks 规则:不能在条件/循环里调用 Hook,否则顺序错乱。
- TS 滥用
any会让类型保护形同虚设;优先用unknown+ 类型收窄。
7. 学习经验¶
经验
- 先理解"为什么需要虚拟 DOM / 组合式",再看 API,记忆更牢。
- 对比学习:把"逻辑复用"在 Vue composable 与 React Hook 各写一遍,差异立刻清晰。
- 性能优化不要过早:先写正确代码,用 Profiler / DevTools 找到瓶颈再优化。
8. 总结¶
| 主题 | Vue 方案 | React 方案 |
|---|---|---|
| 逻辑复用 | composable | 自定义 Hook |
| 更新机制 | patch / 响应式追踪 | Fiber reconcile / 不可变 |
| 性能 | v-memo / shallowRef | memo / useMemo |
| 全栈渲染 | Nuxt 3 | Next.js |
深入底层 → 响应式原理深入(Vue2/3/React):把"更新机制"拆到
defineProperty/Proxy/ 不可变重渲染。下一板块预告:工程化(包管理 / 构建工具 / 模块化 / 代码规范 / Monorepo / CI)。