一、响应式 Hooks —— 业务核心层
1️⃣ ref —— 基础状态 & 可替换值
✅ 实战场景
场景1:表单控件值
js
const keyword = ref('')理由:
- 基本类型
- 需要整体替换
- 双向绑定
场景2:DOM 引用
js
const inputRef = ref(null)
onMounted(() => {
inputRef.value.focus()
})👉 ref 在 DOM 场景是必须的
场景3:loading / visible 控制
js
const loading = ref(false)
const dialogVisible = ref(false)所有布尔控制类,优先用 ref。
2️⃣ reactive —— 复杂对象状态管理
✅ 实战场景
场景1:复杂表单
js
const form = reactive({
name: '',
age: '',
address: {
city: ''
}
})原因:
- 对象结构稳定
- 需要深层响应式
场景2:大页面状态容器
比如:
- 复杂筛选条件
- 表格分页
- 统计面板
js
const state = reactive({
filter: {},
pagination: {},
list: []
})👉 适合“状态容器式”写法。
3️⃣ computed —— 派生状态
✅ 实战场景
场景1:筛选数据
js
const filteredList = computed(() =>
list.value.filter(item => item.name.includes(keyword.value))
)优势:
- 自动缓存
- 避免重复计算
场景2:权限控制
js
const canEdit = computed(() =>
userRole.value === 'admin'
)👉 权限类强烈建议 computed,而不是 watch。
二、watch / watchEffect —— 副作用控制层
4️⃣ watch —— 精准监听
✅ 场景1:接口联动
js
watch(page, () => {
fetchList()
})分页变化 → 自动请求。
✅ 场景2:路由变化
js
watch(
() => route.params.id,
(id) => {
fetchDetail(id)
}
)常用于详情页。
✅ 场景3:深度监听复杂对象
js
watch(
() => form,
() => saveDraft(),
{ deep: true }
)适用于:
- 自动保存草稿
- 实时同步
5️⃣ watchEffect —— 自动依赖收集
✅ 场景1:首屏自动请求
js
watchEffect(() => {
fetchDetail(route.params.id)
})不用手动声明依赖。
✅ 场景2:日志/埋点系统
js
watchEffect(() => {
trackPage(route.path)
})依赖变化自动触发。
三、生命周期 Hooks 实战
6️⃣ onMounted —— 高频使用
✅ 场景
- 初始化接口
- 初始化图表
- 注册监听
js
onMounted(() => {
fetchList()
window.addEventListener('resize', handleResize)
})7️⃣ onUnmounted —— 资源释放
✅ 场景
js
onUnmounted(() => {
window.removeEventListener('resize', handleResize)
clearInterval(timer)
})👉 高频内存泄漏点。
8️⃣ onActivated / onDeactivated —— KeepAlive
✅ 场景:列表页缓存
js
onActivated(() => {
refreshIfNeeded()
})在:
- tab页面
- 多级缓存系统
- 移动端多页面切换
非常常见。
四、组件通信 Hooks 实战
9️⃣ provide / inject —— 复杂组件体系
✅ 场景1:表单组件封装
父组件:
js
provide('formContext', form)子组件:
js
const form = inject('formContext')常见于:
- 表单校验体系
- 表单项注册机制
- 复杂 UI 组件库封装
✅ 场景2:主题系统
js
provide('theme', themeConfig)🔟 defineExpose —— 组件对外API
适用于:
- 弹窗组件
- 表单组件
- 图表组件
js
defineExpose({
open,
close
})父组件可通过 ref 调用。
五、高级场景(加分点)
1️⃣ watch flush 使用时机
js
watch(data, callback, { flush: 'post' })使用场景:
- 依赖 DOM 更新
- 图表刷新
- 需要获取更新后的尺寸
2️⃣ nextTick 使用场景
js
await nextTick()用于:
- 需要获取真实 DOM 尺寸
- 操作滚动条
- 输入框聚焦
3️⃣ getCurrentInstance —— 插件型开发
适用于:
- 获取 proxy
- 全局挂载方法
- 框架层封装
👉 业务代码尽量少用。
六、企业级项目中的“组合式函数”模式(真正高级)
封装 useXXX hooks
例如:
js
function usePagination() {
const page = ref(1)
const pageSize = ref(10)
return { page, pageSize }
}在项目中你可以说:
我们把业务逻辑抽离成 useXXX hooks,形成可复用逻辑层,比如:
- useTable
- useForm
- useRequest
- usePermission
- useResizeObserver
👉 这是高级前端标志。
七、你们项目中 Vue3 hooks 用得最多的是什么?
核心是 ref / reactive 做状态管理, computed 做派生数据, watch 控制副作用, onMounted 做初始化, onUnmounted 控制资源释放, 大型系统中通过封装 useXXX hooks 形成逻辑复用体系。
性能敏感场景会关注 watch 的 flush 时机以及 effect 批量更新机制。
八、加一段架构级
Vue3 hooks 本质是基于 effect + scheduler 构建的响应式副作用系统。 所有生命周期和 watch,本质都是 effect 的不同调度时机。