哈嘍,各位小夥伴,歡迎來到我是wangfang呀的博客!我是我是wangfang呀,雖然還在編程的“菜鳥”階段,但我已經迫不及待地想和大家分享我一路上踩過的坑和學到的小技巧。如果你也曾為bug頭疼,那麼你來對地方了!今天的內容希望能夠給大家帶來一些靈感和幫助。

一、為什麼要引入 Composition API?——Vue 團隊是真的被逼急了 😅

1️⃣ Options API 的“結構性問題”,不是寫法問題

Options API 最大的問題不是“老”,而是當組件複雜後,邏輯會被強行拆散

來看一個典型業務:用户列表 + 搜索 + 請求 + loading + 錯誤處理

在 Options API 裏,你會得到這樣的結構:

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:歷史遺留之痛

mixins: [listMixin, searchMixin]

痛點你肯定踩過:

  • 命名衝突(methods/data 誰覆蓋誰?)
  • 來源不透明(這個方法到底從哪來的?)
  • 邏輯耦合嚴重(刪一個 mixin,全組件爆炸)

👉 mixin 最大的問題:不是顯式依賴


2️⃣ Composition API:用“函數”做邏輯單元

Composition API 的複用單位不是組件,是 **函數(Composable)**。

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(邏輯被拆散)

data() { return { count: 0 } }
methods: {
  inc() { this.count++ }
}

Composition API(邏輯內聚)

const count = ref(0)
const inc = () => count.value++

看起來只是“換個地方寫”,但一旦功能多起來,差距會指數級放大。


2️⃣ 思維模型對比

維度 Options API Composition API
組織方式 按配置類型 按業務邏輯
複用能力 mixins(弱) composables(強)
類型推導 困難 天生友好
可拆分性 極強
大型項目 易失控 更可維護

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


四、可維護性分析:Composition API 為什麼更適合“活得久”的項目?🧩

1️⃣ 可維護性 = 可理解性 + 可修改性

Composition API 在這兩點上優勢非常明顯:

✅ 邏輯集中

// useSearch.ts
export function useSearch(fetcher) {
  const keyword = ref('')
  watch(keyword, () => fetcher(keyword.value))
  return { keyword }
}

誰看這段代碼都知道:

“哦,這是搜索邏輯。”


2️⃣ 對 TypeScript 極其友好(這是 Vue3 的關鍵戰場)

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(節選)

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

問題:

  • 請求邏輯 + 搜索邏輯 + 狀態全混在一起
  • 無法複用
  • 測試困難

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

useList.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

export function useSearch(onSearch) {
  const keyword = ref('')
  watch(keyword, () => onSearch(keyword.value))
  return { keyword }
}

組件中組合

const { list, loading, fetchList } = useList()
const { keyword } = useSearch(fetchList)

onMounted(() => fetchList())

✨ 重構後的收益:

  • 每段邏輯職責單一
  • 可單獨測試
  • 可跨組件複用
  • 閲讀成本直線下降

六、一句“醒腦總結”(送你當文章結尾 😏)

  Composition API 從來不是為了“寫得更高級”, 而是為了回答一個更現實的問題: 當你的業務越來越複雜時,你的代碼還能不能被人看懂?

所以我最後反問你一句: 如果一年後是你自己來維護這段代碼,你希望它長得像 Options API,還是像 Composition API? 😉

好啦,今天的內容就先到這裏!如果覺得我的分享對你有幫助,給我點個贊,順便評論吐個槽,當然不要忘了三連哦!感謝大家的支持,記得常回來,我是wangfang呀等着你們的下一次訪問!