uni-app 從 Options API 遷移到 Composition API 的詳細指南
一、遷移前的準備
-
升級環境:
- 確保 HBuilderX 版本 ≥ 3.2.0
- 項目 uni-app 版本 ≥ 3.0.0
-
了解 Composition API 基礎:
- 響應式系統:
ref
、reactive
- 生命周期鉤子:
onMounted
、onUnload
等 - 組合函數:提取可復用邏輯
- 響應式系統:
-
備份項目:
- 遷移前務必備份代碼
- 建議使用版本控制系統(如 Git)
二、漸進式遷移策略
-
組件級別遷移:
- 先遷移簡單、獨立的組件
- 再處理復雜、依賴多的組件
-
功能模塊遷移:
- 先遷移數據邏輯
- 再遷移生命周期鉤子
- 最后處理計算屬性和監聽器
-
保持兩種 API 并存:
- 遷移期間允許兩種 API 在項目中共存
- 新組件使用 Composition API,舊組件逐步遷移
三、基礎語法遷移
1. 數據定義
// Options API
export default {data() {return {count: 0,user: {name: 'John',age: 30}};}
}// Composition API
import { ref, reactive } from 'vue';export default {setup() {// 基本類型用 refconst count = ref(0);// 對象用 reactiveconst user = reactive({name: 'John',age: 30});return {count,user};}
}
2. 方法定義
// Options API
export default {methods: {increment() {this.count++;}}
}// Composition API
import { ref } from 'vue';export default {setup() {const count = ref(0);const increment = () => {count.value++;};return {count,increment};}
}
3. 計算屬性
// Options API
export default {computed: {doubleCount() {return this.count * 2;}}
}// Composition API
import { ref, computed } from 'vue';export default {setup() {const count = ref(0);const doubleCount = computed(() => count.value * 2);return {count,doubleCount};}
}
4. 監聽器
// Options API
export default {watch: {count(newVal, oldVal) {console.log('count changed:', newVal, oldVal);}}
}// Composition API
import { ref, watch } from 'vue';export default {setup() {const count = ref(0);watch(count, (newVal, oldVal) => {console.log('count changed:', newVal, oldVal);});return {count};}
}
四、生命周期鉤子遷移
// Options API
export default {onLoad() {console.log('頁面加載');},onShow() {console.log('頁面顯示');},onUnload() {console.log('頁面卸載');}
}// Composition API
import { onLoad, onShow, onUnload } from 'vue';export default {setup() {onLoad(() => {console.log('頁面加載');});onShow(() => {console.log('頁面顯示');});onUnload(() => {console.log('頁面卸載');});return {};}
}
五、組合函數提取復用邏輯
// Options API (mixins)
const counterMixin = {data() {return {count: 0};},methods: {increment() {this.count++;}}
};export default {mixins: [counterMixin]
}// Composition API (組合函數)
// useCounter.js
import { ref } from 'vue';export function useCounter(initialValue = 0) {const count = ref(initialValue);const increment = () => {count.value++;};return {count,increment};
}// 組件中使用
import { useCounter } from './useCounter';export default {setup() {const { count, increment } = useCounter(5);return {count,increment};}
}
六、使用 <script setup>
簡化語法
<template><view><text>{{ count }}</text><button @click="increment">+1</button></view>
</template><script setup>
import { ref, onLoad } from 'vue';// 響應式數據
const count = ref(0);// 方法
const increment = () => {count.value++;
};// 生命周期鉤子
onLoad(() => {console.log('頁面加載');
});
</script>
七、處理組件通信
1. Props
// Options API
export default {props: {message: String},methods: {handleClick() {console.log(this.message);}}
}// Composition API
import { defineProps } from 'vue';export default {props: {message: String},setup(props) {const handleClick = () => {console.log(props.message);};return {handleClick};}
}// 或使用 <script setup>
<script setup>
const props = defineProps({message: String
});const handleClick = () => {console.log(props.message);
};
</script>
2. Emits
// Options API
export default {emits: ['update'],methods: {triggerUpdate() {this.$emit('update', 'new value');}}
}// Composition API
import { defineEmits } from 'vue';export default {emits: ['update'],setup(props, { emit }) {const triggerUpdate = () => {emit('update', 'new value');};return {triggerUpdate};}
}// 或使用 <script setup>
<script setup>
const emit = defineEmits(['update']);const triggerUpdate = () => {emit('update', 'new value');
};
</script>
八、處理特殊情況
1. 訪問實例屬性
// Options API
export default {methods: {callMethod() {this.$refs.myRef.focus();}}
}// Composition API
import { getCurrentInstance } from 'vue';export default {setup() {const { proxy } = getCurrentInstance();const callMethod = () => {proxy.$refs.myRef.focus();};return {callMethod};}
}
2. 處理 ref
// Options API
export default {mounted() {this.$refs.myRef.focus();}
}// Composition API
import { ref, onMounted } from 'vue';export default {setup() {const myRef = ref(null);onMounted(() => {myRef.value.focus();});return {myRef};}
}
九、測試與驗證
-
單元測試:
- 確保遷移后的組件行為不變
- 使用 Vue Test Utils 3.0+ 測試 Composition API
-
集成測試:
- 驗證組件間交互正常
- 測試路由、狀態管理等集成功能
-
性能測試:
- 對比遷移前后的內存使用
- 驗證響應式系統性能
十、遷移建議
-
從簡單組件開始:
- 先遷移無依賴的基礎組件
- 再遷移復雜業務組件
-
利用工具輔助:
- 使用 IDE 插件(如 Vetur)提供的代碼轉換功能
- 參考 Vue 官方遷移工具
-
團隊培訓:
- 組織 Composition API 培訓
- 編寫內部遷移指南和最佳實踐
-
持續重構:
- 新功能優先使用 Composition API
- 逐步重構舊組件
總結
從 Options API 遷移到 Composition API 是一個漸進的過程,需要耐心和規劃。建議采用"組件級別遷移"和"功能模塊遷移"相結合的策略,先易后難,逐步推進。在遷移過程中,充分利用 Composition API 的優勢,如邏輯復用、更好的 TypeScript 支持等,提高代碼質量和可維護性。