Composition API 设计思想(第11节)

一、为什么要引入 Composition API?------Vue 团队是真的被逼急了 😅

1️⃣ Options API 的"结构性问题",不是写法问题

Options API 最大的问题不是"老",而是当组件复杂后,逻辑会被强行拆散

来看一个典型业务:用户列表 + 搜索 + 请求 + loading + 错误处理

在 Options API 里,你会得到这样的结构:

js 复制代码
export default {
  data() {
    return {
      list: [],
      loading: false,
      keyword: '',
      error: null
    }
  },
  methods: {
    async fetchList() { /* ... */ },
    onSearch() { /* ... */ }
  },
  watch: {
    keyword() { /* 触发搜索 */ }
  },
  created() {
    this.fetchList()
  }
}

问题在哪?

  • 一个"列表请求"的逻辑,被拆进了 data / methods / watch / 生命周期
  • 逻辑的时间顺序业务意图被结构打断
  • 想复用?复制一整坨 options,再删删改改 😵‍💫

👉 Vue 官方在 RFC 里就点名了这个问题:
Options API 不利于复杂逻辑的组织与复用。

2️⃣ Composition API 的核心动机:按"逻辑"组织代码

Composition API 的第一性原理只有一句话:

把"相关的逻辑"写在一起,而不是把"同类型的代码"写在一起。

这不是语法升级,这是代码组织方式的升级

二、逻辑复用问题:Composition API 是怎么"正面硬刚"的?🧠

1️⃣ Options API 的复用方式有多痛?

mixins:历史遗留之痛
js 复制代码
mixins: [listMixin, searchMixin]

痛点你肯定踩过:

  • 命名冲突(methods/data 谁覆盖谁?)
  • 来源不透明(这个方法到底从哪来的?)
  • 逻辑耦合严重(删一个 mixin,全组件爆炸)

👉 mixin 最大的问题:不是显式依赖

2️⃣ Composition API:用"函数"做逻辑单元

Composition API 的复用单位不是组件,是 函数(Composable)

js 复制代码
export function useList() {
  const list = ref([])
  const loading = ref(false)

  async function fetchList() {
    loading.value = true
    // ...
    loading.value = false
  }

  return { list, loading, fetchList }
}

这一下,问题全解决了:

  • 依赖显式(import 什么就用什么)
  • 命名空间天然隔离
  • 可组合、可测试、可拆分

👉 逻辑像乐高,而不是像面团。

三、对比 Options API:不是"谁淘汰谁",而是"谁更适合复杂度"⚖️

1️⃣ 写法对比(同一个功能)

Options API(逻辑被拆散)
js 复制代码
data() { return { count: 0 } }
methods: {
  inc() { this.count++ }
}
Composition API(逻辑内聚)
js 复制代码
const count = ref(0)
const inc = () => count.value++

看起来只是"换个地方写",但一旦功能多起来,差距会指数级放大。

2️⃣ 思维模型对比

维度 Options API Composition API
组织方式 按配置类型 按业务逻辑
复用能力 mixins(弱) composables(强)
类型推导 困难 天生友好
可拆分性 极强
大型项目 易失控 更可维护

👉 Options API 不是不能用,而是复杂度一高就很吃力

四、可维护性分析:Composition API 为什么更适合"活得久"的项目?🧩

1️⃣ 可维护性 = 可理解性 + 可修改性

Composition API 在这两点上优势非常明显:

✅ 逻辑集中
js 复制代码
// useSearch.ts
export function useSearch(fetcher) {
  const keyword = ref('')
  watch(keyword, () => fetcher(keyword.value))
  return { keyword }
}

谁看这段代码都知道:

"哦,这是搜索逻辑。"

2️⃣ 对 TypeScript 极其友好(这是 Vue3 的关键战场)

ts 复制代码
export function useUser() {
  const user = ref<User | null>(null)
  function setUser(u: User) {
    user.value = u
  }
  return { user, setUser }
}
  • 自动推导
  • IDE 友好
  • 重构安全

👉 Vue3 + Composition API + TS,不是噱头,是工程现实。

五、实战重构示例:把一个"难维护组件"拆干净 💪

1️⃣ 原始 Options API(节选)

js 复制代码
export default {
  data() {
    return {
      list: [],
      loading: false,
      keyword: ''
    }
  },
  methods: {
    async fetchList() { /* ... */ }
  },
  watch: {
    keyword() {
      this.fetchList()
    }
  },
  mounted() {
    this.fetchList()
  }
}

问题:

  • 请求逻辑 + 搜索逻辑 + 状态全混在一起
  • 无法复用
  • 测试困难

2️⃣ Composition API 重构(分而治之)

useList.ts
ts 复制代码
export function useList() {
  const list = ref([])
  const loading = ref(false)

  async function fetchList(keyword = '') {
    loading.value = true
    // mock fetch
    list.value = []
    loading.value = false
  }

  return { list, loading, fetchList }
}
useSearch.ts
ts 复制代码
export function useSearch(onSearch) {
  const keyword = ref('')
  watch(keyword, () => onSearch(keyword.value))
  return { keyword }
}
组件中组合
ts 复制代码
const { list, loading, fetchList } = useList()
const { keyword } = useSearch(fetchList)

onMounted(() => fetchList())

✨ 重构后的收益:

  • 每段逻辑职责单一
  • 可单独测试
  • 可跨组件复用
  • 阅读成本直线下降

六、一句"醒脑总结"(送你当文章结尾 😏)

Composition API 从来不是为了"写得更高级",

而是为了回答一个更现实的问题:
当你的业务越来越复杂时,你的代码还能不能被人看懂?

所以我最后反问你一句:
如果一年后是你自己来维护这段代码,你希望它长得像 Options API,还是像 Composition API? 😉

相关推荐
冴羽8 小时前
2025 年最火的前端项目出炉,No.1 易主!
前端·javascript·node.js
wordbaby8 小时前
Flexbox 布局中的滚动失效问题:为什么需要 `min-h-0`?
前端·css
黛色正浓8 小时前
leetCode-热题100-滑动窗口合集(JavaScript)
javascript·算法·leetcode
asdfg12589638 小时前
小程序开发中的JS和Go的对比及用途
开发语言·javascript·golang
demo007x8 小时前
在国内也能使用 Claude cli给自己提效,附实操方法
前端·后端·程序员
FL16238631298 小时前
基于yolo11实现的车辆实时交通流量进出统计与速度测量系统python源码+演示视频
开发语言·python·音视频
jayaccc8 小时前
Webpack配置详解与实战指南
前端·webpack·node.js
南囝coding8 小时前
发现一个宝藏图片对比工具!速度比 ImageMagick 快 6 倍,还是开源的
前端
华如锦8 小时前
四:从零搭建一个RAG
java·开发语言·人工智能·python·机器学习·spring cloud·计算机视觉
前端小黑屋8 小时前
查看 Base64 编码的字体包对应的字符集
前端·css·字体