Vue 3 Composition API 实战:从 Options API 到 Composables 思维转型

Vue 3 Composition API 实战:从 Options API 到 Composables 思维转型

Ethan
2025-04-25 发布 / 正在检测是否收录...

Vue 3 的 Composition API 不仅仅是一种新的 API 风格,它代表了一种全新的代码组织思维——从"按选项类型组织"转向"按逻辑关注点组织"。本文将从一个真实项目的重构案例出发,深入讲解 Composition API 的实战技巧。

Options API 的痛点:逻辑碎片化

考虑一个典型的搜索组件,使用 Options API 编写时,一个功能(搜索)的逻辑会散落在 data、watch、methods、mounted、beforeUnmount 等多个选项中。当组件变得复杂时,在数百行代码中追踪一个功能的完整逻辑变得极其困难。

Composition API 的解决方案:按功能聚合

同样的搜索功能,用 Composition API 重写后,所有搜索相关的逻辑——状态、副作用、清理——都被封装在一个 composable 函数中。这就是 Composable(组合函数) 的核心思想。

function useSearch() {\n  const keyword = ref('');\n  const results = ref([]);\n  const loading = ref(false);\n  let timer = null;\n\n  async function search() {\n    loading.value = true;\n    try { results.value = await fetchResults(keyword.value); }\n    finally { loading.value = false; }\n  }\n\n  function debounceSearch(val) {\n    clearTimeout(timer);\n    timer = setTimeout(() => { if (val.trim()) search(); }, 300);\n  }\n\n  watch(keyword, debounceSearch);\n  onBeforeUnmount(() => clearTimeout(timer));\n\n  return { keyword, results, loading, search };\n}

ref vs reactive:何时用哪个?

// ref:适用于基本类型和需要整体替换的场景\nconst count = ref(0);\nconst user = ref({ name: '张三' });\ncount.value++; // 需要 .value\nuser.value = { name: '李四' }; // 可以整体替换\n\n// reactive:适用于复杂对象,不需要 .value\nconst state = reactive({ user: { name: '张三' }, settings: { theme: 'dark' } });\nstate.user.name = '李四'; // 直接访问,无 .value\n\n// reactive 的限制:不能整体替换\nlet state = reactive({ count: 0 });\nstate = reactive({ count: 1 }); // 破坏了响应式引用\n// 用 ref 包装对象避免此问题

实战建议:对于组件内部状态,优先使用 ref(更灵活,类型推断更好);对于包含多个相关属性的配置对象,使用 reactive。

Composable 设计原则

1. 单一职责

一个 Composable 只做一件事。如果 useUser() 既管理用户认证又管理用户偏好设置,应该拆分为 useAuth() 和 usePreferences()。

2. 可配置而非硬编码

function useSearch({ debounceMs = 300, minLength = 2 } = {}) { /* ... */ }

3. 清理副作用

function useEventListener(target, event, handler) {\n  onMounted(() => target.addEventListener(event, handler));\n  onBeforeUnmount(() => target.removeEventListener(event, handler));\n}

实战案例:可复用的数据获取 Composable

function useFetch(url) {\n  const data = ref(null);\n  const error = ref(null);\n  const loading = ref(false);\n\n  async function execute() {\n    loading.value = true; error.value = null;\n    try {\n      const response = await fetch(url);\n      if (!response.ok) throw new Error('请求失败');\n      data.value = await response.json();\n    } catch (e) { error.value = e.message; }\n    finally { loading.value = false; }\n  }\n\n  if (isRef(url)) { watch(url, execute, { immediate: true }); }\n  else { execute(); }\n\n  return { data, error, loading, refetch: execute };\n}

从 Options API 迁移的渐进策略

不需要一次性重写整个项目:新组件直接用 Composition API,提取可复用的 Composable 从现有 mixin 开始转化,复杂组件(超过 300 行)逐个重构,利用 setup 语法糖进一步简化代码。Options API 不会消失——对于简单组件,它仍然是非常好的选择。Composition API 的价值主要体现在复杂组件的逻辑组织和跨组件的逻辑复用

© 版权声明
THE END
喜欢就支持一下吧
点赞 1 分享 收藏

评论 (0)

取消

Warning: file_put_contents(/var/www/html/usr/cache/pagecache/98/989de16a99d51f029ea77ba7f3bf6e82.cache): failed to open stream: No such file or directory in /var/www/html/usr/plugins/PageCache/Plugin.php on line 188