Skip to content

一、响应式 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 的不同调度时机。