以下是 Vue 2 的響應式 API 和 Vue 3 的組合式 API 的詳細對比,從核心機制、使用方式、代碼示例及優缺點展開:
1. Vue 2 的響應式 API
核心機制
- 基于
Object.defineProperty
:- 通過劫持對象的
getter
和setter
實現數據變化追蹤。 - 限制:無法檢測屬性的添加/刪除,且不支持數組的某些變異操作(如直接修改索引
arr[0] = ...
)。
- 通過劫持對象的
主要 API
功能 | 實現方式 | 示例 |
---|---|---|
聲明響應式數據 | data 對象或 Vue.set /this.$set 添加屬性 | ```javascript |
data() { return { count: 0 }; } ``` |
|
| 計算屬性 | computed
對象 | javascript <br>computed: { fullName() { return this.firstName + this.lastName; } }<br>
|
| 偵聽器 | watch
對象或 this.$watch
方法 | javascript <br>watch: {<br> count: (newVal) => console.log(newVal)<br>}<br>
|
| 方法 | methods
對象 | javascript <br>methods: { increment() { this.count++; } }<br>
|
生命周期鉤子
- 分散在 Options 中:如
created
,mounted
,beforeDestroy
等。
2. Vue 3 的組合式 API
核心機制
- 基于
Proxy
:- 全局響應式追蹤,支持檢測屬性的增刪改,且無需
Vue.set
。 - 優勢:更高效、更靈活,支持
for...in
遍歷和數組變異操作。
- 全局響應式追蹤,支持檢測屬性的增刪改,且無需
核心函數
函數 | 用途 | 示例 |
---|---|---|
reactive | 將對象轉為響應式(返回 Proxy) | ```javascript |
const state = reactive({ count: 0 }); ``` |
|
| ref
| 將基本類型轉為響應式(返回一個 .value
對象) | javascript <br>const count = ref(0);<br>
|
| computed
| 聲明計算屬性(返回響應式引用) | javascript <br>const fullName = computed(() => state.firstName + state.lastName);<br>
|
| watch
| 監聽數據變化(支持更靈活的選項) | javascript <br>watch(count, (newVal) => console.log(newVal));<br>
|
| onMounted
| 生命周期鉤子(組合式 API 形式) | javascript <br>onMounted(() => console.log('Mounted'));<br>
|
核心函數對比
功能 | Vue 2 | Vue 3 | 說明 |
---|---|---|---|
響應式數據 | data 對象 | reactive /ref | Vue 3 需顯式聲明響應式,支持更靈活的類型(對象/基本類型)。 |
計算屬性 | computed 對象 | computed() 函數 | Vue 3 需通過函數聲明,返回值需手動返回到模板。 |
偵聽器 | watch 對象 | watch() 函數 | Vue 3 支持更靈活的選項(如 deep , immediate )。 |
方法 | methods 對象 | setup() 返回函數 | Vue 3 在 setup() 中定義方法并返回,無需 this 。 |
3. 組合式 API 核心特性
(1) setup()
函數
- 入口點:所有邏輯集中在此函數中,替代 Options API 的分散選項。
- 執行時機:在
beforeCreate
和created
之前執行。 - 返回值:需返回一個對象,暴露給模板或子組件。
(2) ref
vs reactive
函數 | 適用場景 | 示例 |
---|---|---|
ref | 基本類型(如數字、字符串)或需要直接訪問值的場景 | ```javascript |
const count = ref(0); console.log(count.value); ``` | ||
reactive | 復雜對象(如對象、數組)或需要直接操作屬性的場景 | ```javascript |
const state = reactive({ count: 0 }); console.log(state.count); ``` | ||
(3) 生命周期鉤子
- 組合式形式:通過
onXXX
前綴的函數聲明(如onMounted
,onBeforeUnmount
)。 - 無需
this
:直接在setup()
中調用,無需通過this
訪問。
4. 代碼示例對比
(1) 聲明響應式數據
// Vue 2(Options API)
export default {data() {return { count: 0 };}
};// Vue 3(組合式 API)
import { ref } from 'vue';export default {setup() {const count = ref(0);return { count };}
};
(2) 計算屬性
// Vue 2
export default {computed: {fullName() {return this.firstName + ' ' + this.lastName;}}
};// Vue 3
import { computed } from 'vue';export default {setup() {const state = reactive({firstName: 'John',lastName: 'Doe'});const fullName = computed(() => state.firstName + ' ' + state.lastName);return { fullName };}
};
(3) 生命周期
// Vue 2
export default {mounted() {console.log('Mounted');}
};// Vue 3
import { onMounted } from 'vue';export default {setup() {onMounted(() => console.log('Mounted'));return {};}
};
5. 對比總結表格
特性 | Vue 2 | Vue 3(組合式 API) | 優勢/差異 |
---|---|---|---|
響應式核心 | Object.defineProperty | Proxy | Vue 3 支持屬性增刪和更靈活的數組操作。 |
數據聲明 | data 對象 | reactive /ref 顯式聲明 | Vue 3 需顯式聲明響應式,避免隱式問題。 |
計算屬性 | computed 對象 | computed() 函數 | Vue 3 更靈活,支持返回函數或對象。 |
偵聽器 | watch 對象 | watch() 函數 | Vue 3 支持更細粒度的選項(如 deep , flush )。 |
方法 | methods 對象 | setup() 返回函數 | Vue 3 邏輯集中,減少 Options 耦合。 |
生命周期鉤子 | 分散在 Options 中 | onXXX 函數集中聲明 | Vue 3 鉤子名更規范(如 onMounted ),無需 this 。 |
代碼復用 | Mixins(易沖突) | 自定義組合函數(無污染) | 組合式 API 更易復用且避免命名沖突。 |
模板綁定 | this.count | count (通過 ref )或 state.count (通過 reactive ) | Vue 3 需通過 ref.value 或 reactive 對象訪問值。 |
6. 遷移建議
- 逐步遷移:在 Vue 2 項目中可通過
@vue/composition-api
漸進式引入組合式 API。 - 優先使用組合式 API:在新項目中推薦使用組合式 API,因其更靈活、可維護。
- 注意
ref
和reactive
的區別:根據數據類型選擇合適的方式聲明響應式。 - 生命周期鉤子替換:Vue 3 的
setup()
會提前執行,需調整初始化邏輯順序。
如需更詳細示例,可參考 Vue 3 官方文檔。