大家好,我是程序员柏风,AI 最全的 Vibecoding 学习地图 http://coderoadmap.cn 作者。
组合式 API 深入
这一课你将能做到
- 说出
<script setup>与生命周期钩子(onMounted等)的用法 - 抽一个可复用的 composable(如
useToggle),并在两个组件使用 - 对照 React Custom Hooks:复用「有状态逻辑」而不是复用 UI 模板
为什么要学
Options API 把相关逻辑拆到 data/methods/mounted 各段,大组件会碎。
组合式 API 按功能把状态、方法、侦听、生命周期放在一起;再抽成 useXxx 跨组件复用——对标 React Hooks 思路。
先建立图像
组件 A 组件 B
useToggle() useToggle()
useTrackList() …
↘ composables/useToggle.js
| 概念 | Vue | React |
|---|---|---|
| 组合单元 | composable useXxx | custom hook useXxx |
| 挂载后 | onMounted | useEffect(() => {}, []) |
| 卸载 | onUnmounted | effect cleanup |
跟着做
步骤 1:生命周期最小例
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
const now = ref("");
let timer;
onMounted(() => {
timer = setInterval(() => {
now.value = new Date().toLocaleTimeString();
}, 1000);
});
onUnmounted(() => clearInterval(timer));
</script>
<template>
<p>{{ now }}</p>
</template>
进入页面开始跳秒;离开组件应清定时器(路由切换时验证)。
步骤 2:抽取 useToggle
// composables/useToggle.js
import { ref } from "vue";
export function useToggle(initial = false) {
const on = ref(initial);
function toggle() {
on.value = !on.value;
}
function set(v) {
on.value = v;
}
return { on, toggle, set };
}
步骤 3:两处使用
<script setup>
import { useToggle } from "./composables/useToggle";
const { on, toggle } = useToggle();
</script>
<template>
<button type="button" @click="toggle">{{ on ? "开" : "关" }}</button>
</template>
再在另一个组件同样 import——状态各自独立,逻辑一份。
步骤 4:composable 内使用生命周期
import { ref, onMounted } from "vue";
export function usePageTitle(title) {
onMounted(() => {
document.title = title;
});
}
规则:只在 setup 同步期间调用 composable(与 Hooks 规则同构:别在条件分支里随机调用)。
步骤 5:整理大组件
把「列表过滤 + 本地存储」相关的 ref/computed/watch 挪进 useLessonFilter.js,组件里只剩拼模板。
目标:打开 script 能按功能块阅读,而不是按 options 分段跳跃。
步骤 6:对照 React Hook 文件
若你有 useXxx 的 React 练习,并排看:都是「返回状态与函数」。
差别:Vue 返回的常是 ref,模板自动解包;React 返回的是 state 值与 setter。
讲清楚要点
<script setup>就是组合式的语法糖:顶层绑定进模板。- 按功能组织,不按选项类型组织。
- composable 命名
use前缀:约定,利于检索。 - 副作用必清理:定时器、监听器、订阅在
onUnmounted释放。 - 不要在异步回调里才第一次调用 composable。
- UI 复用靠组件,逻辑复用靠 composable——两者互补。
你可能会懵的地方
-
和 mixins?
mixins 易冲突、来源不清;组合式更明确。新代码别开 mixin 坑。 -
setup()函数写法?
仍支持;日常 SFC 优先生script setup。 -
TypeScript 泛型 composable?
可以;类型细节见 TS 课。 -
provide/inject 放哪?
也可包进 composable(useTheme);别滥用跨全树隐式依赖。 -
测试?
composable 可抽测;入门先手动点验。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
| 条件里偶尔调用 useXxx | 顺序乱、难维护 | setup 顶层稳定调用 |
| 定时器不清理 | 泄漏、报错 | onUnmounted |
| 一个 composable 干十件事 | 难复用 | 按功能拆 |
| 用 mixin 堆全局 | 命名冲突 | composable |
| 把 DOM 结构塞进 composable 返回 | 职责混 | 逻辑与组件分离 |
| 照抄 React effect 依赖数组思维硬套 | API 不适配 | 用 watch 明确源 |
自测三问
- composable 与组件各复用什么?
- 为何生命周期副作用要成对出现(注册/清理)?
- 和 React Hooks「只在顶层调用」规则如何对应?
小结一句话
组合式 API 按功能聚合逻辑;用 composable 复用有状态行为,并用生命周期管理副作用边界。
动手加深
把本课「跟着做」再跑一遍,但这次故意先写出错法表里的一种写法,观察报错或错误现象 30 秒,再改回正解。
用自己的话补三条笔记:① 我最容易踩的坑;② 成功时屏幕/结果长什么样;③ 本课与上一课的衔接点。写不出来就重做步骤,不要只标完成。
官方延伸
- 组合式 API 常见问答
- 生命周期
- 下一课:Vue Router