[Medium] Composition API vs Options API
1. What is Composition API?
什麼是 Composition API?
Composition API 是 Vue 3 引入的一種新的組件寫法,它提供了一種更靈活的方式來組織組件邏輯。與傳統的 Options API 不同,Composition API 允許我們將相關的邏輯組織在一起,而不是分散在不同的選項中。
Options API(傳統寫法)
<template>
<div>
<p>{{ fullName }}</p>
<button @click="increment">Count: {{ count }}</button>
</div>
</template>
<script>
export default {
data() {
return {
firstName: 'John',
lastName: 'Doe',
count: 0,
};
},
computed: {
fullName() {
return `${this.firstName} ${this.lastName}`;
},
},
methods: {
increment() {
this.count++;
},
},
mounted() {
console.log('Component mounted');
},
};
</script>
Composition API(新寫法)
<template>
<div>
<p>{{ fullName }}</p>
<button @click="increment">Count: {{ count }}</button>
</div>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue';
// 相關的邏輯組織在一起
const firstName = ref('John');
const lastName = ref('Doe');
const fullName = computed(() => `${firstName.value} ${lastName.value}`);
const count = ref(0);
const increment = () => {
count.value++;
};
onMounted(() => {
console.log('Component mounted');
});
</script>
2. Composition API vs Options API: Key Differences
Composition API 與 Options API 的主要差異
1. 邏輯組織方式
Options API:邏輯分散在不同的選項中
<script>
export default {
// 資料分散在各處
data() {
return {
user: null,
posts: [],
comments: [],
};
},
computed: {
// 計算屬性分散
userName() {
return this.user?.name;
},
postCount() {
return this.posts.length;
},
},
methods: {
// 方法分散
fetchUser() {
/* ... */
},
fetchPosts() {
/* ... */
},
fetchComments() {
/* ... */
},
},
mounted() {
// 生命週期分散
this.fetchUser();
this.fetchPosts();
},
};
</script>
Composition API:相關邏輯組織在一起
<script setup>
import { ref, computed, onMounted } from 'vue';
// 使用者相關邏輯
const user = ref(null);
const userName = computed(() => user.value?.name);
const fetchUser = async () => {
// ...
};
// 文章相關邏輯
const posts = ref([]);
const postCount = computed(() => posts.value.length);
const fetchPosts = async () => {
// ...
};
// 評論相關邏輯
const comments = ref([]);
const fetchComments = async () => {
// ...
};
// 生命週期
onMounted(() => {
fetchUser();
fetchPosts();
});
</script>
2. 程式碼重用
Options API:使用 Mixins(容易產生命名衝突)
<script>
// UserMixin.js
export default {
data() {
return {
user: null,
};
},
methods: {
fetchUser() {
// ...
},
},
};
// Component.vue
import UserMixin from './UserMixin';
export default {
mixins: [UserMixin],
// 如果有多個 mixin,容易產生命名衝突
};
</script>
Composition API:使用 Composables(更靈活)
<script setup>
// useUser.js
import { ref } from 'vue';
export function useUser() {
const user = ref(null);
const fetchUser = async () => {
// ...
};
return { user, fetchUser };
}
// Component.vue
import { useUser } from './useUser';
const { user, fetchUser } = useUser();
// 可以選擇性地使用,避免命名衝突
</script>
3. TypeScript 支援
Options API:TypeScript 支援有限
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
data() {
return {
count: 0, // 型別推斷可能不準確
};
},
methods: {
increment() {
this.count++; // this 的型別可能不準確
},
},
});
</script>
Composition API:完整的 TypeScript 支援
<script setup lang="ts">
import { ref } from 'vue';
const count = ref<number>(0); // 明確的型別
const increment = (): void => {
count.value++;
};
</script>
3. 比較表
| 特性 | Options API | Composition API |
|---|---|---|
| 學習曲線 | 較低 | 較高 |
| 邏輯組織 | 分散在不同選項 | 相關邏輯集中 |
| 程式碼重用 | Mixins(容易衝突) | Composables(靈活) |
| TypeScript 支援 | 有限 | 完整支援 |
| 適用場景 | 簡單組件 | 複雜組件、大型專案 |
| 向後相容 | Vue 2/3 都支援 | Vue 3 專屬 |
4. Common Interview Questions
常見面試題目
題目 1:選擇 API 風格
請說明在什麼情況下應該使用 Composition API,什麼情況下使用 Options API?
點擊查看答案
使用 Composition API 的情況:
-
複雜組件:邏輯複雜,需要更好的組織
<script setup>
// 多個功能模組,使用 Composition API 更清晰
const { user, fetchUser } = useUser();
const { posts, fetchPosts } = usePosts();
const { comments, fetchComments } = useComments();
</script> -
需要程式碼重用:多個組件共享邏輯
<script setup>
// 使用 composable 函式,易於重用
const { count, increment, decrement } = useCounter();
</script> -
TypeScript 專案:需要完整的型別支援
<script setup lang="ts">
// Composition API 對 TypeScript 支援更好
const count = ref<number>(0);
</script> -
大型專案:需要更好的邏輯組織和維護
使用 Options API 的情況:
-
簡單組件:邏輯簡單,不需要複雜組織
<script>
export default {
data() {
return { count: 0 };
},
methods: {
increment() {
this.count++;
},
},
};
</script> -
Vue 2 專案:需要向後相容
-
團隊熟悉度:團隊更熟悉 Options API
建議:
- 新專案優先使用 Composition API
- 簡單組件可以繼續使用 Options API
- 複雜組件建議使用 Composition API