最近一直在寫 Vue, 在公司的項目裡使用的是Composition Api + Vue2 的組合. (因為公司裡考慮到同事的技能樹, 沒有用vue3和Typescipt).
CA 是 Vue3 追加的全新 API. 用到 Vue2 裡可能有點怪怪的.
不過 CA 是以 Vue-Plugin 的方式提供的 API, 所以使用起來非常方便. 同時也鼓勵更多人使用這個API.
首先是關於這個API的使用方式, 以前的代碼需要將方法卸載method區塊中, 每個變量和方法之間的關係很模糊曖昧.
需要開發者自己去找關於每個方法和變量之間的關係, 用CA之後可以寫出類似ReactHook風格的代碼.
1// OA (Option API 原版的API是這樣稱呼的)
2{
3 data: {
4 count: 1
5 },
6 methods: {
7 sub(num: number) {
8 // ...
9 },
10 add(num: number) {
11 // ...
12 }
13 }
14}
15// CA
16const count = ref(1);
17const { add, sub } = useCount();
18
19add(1);
20sub(2);
21
22function useCount(count: Ref<number>) {
23 function sub(num: number) {
24 // ...
25 },
26 function add(num: number) {
27 // ...
28 }
29}
30
31// 當然你也可以像ReactHook那樣寫, 完全沒有問題,看你的個人口味
32const { count, add, sub } = useCount(0);
33
34add(1);
35sub(2);
36
37function useCount(count: number) {
38 const count = ref(count);
39 function sub(num: number) {
40 // ...
41 },
42 function add(num: number) {
43 // ...
44 }
45}
我目前寫CA大概就是這樣編寫的. 根據一個響應數據的關係編寫改變它的一系列動作. 這樣邏輯拆分的很清楚. 查看起來也比較方便.
不過這套API目前的缺點也比較明顯, 在開發過程中從Vue2過來的用戶很明顯能感覺到,
在setup()由於不能使用this所以會有很多開發習慣上的麻煩.
這裡說個關於使用this上掛載對象的方法. (ctx參數不說了)
- 首先就是CA的庫中有一個函數,叫做
getCurrentInstall. 可以通過該函數獲得當前組件的實例. 使用該實例上代理的對象就能控制各種this.$router,this.$refs方法了. - 第二種可以讓你使用
this, 把動作函數掛載到某個視圖按鈕上的時候, 在該動作函數里就可以使用this對象. 上面有正常OA可以使用的所有this上掛載的對象.
開發項目的時候還踩了很多坑, 不過都是一些智商問題… 比如JS的對象傳遞傳遞的是Reference, 基本類型是Clone. 因為這個原因有幾個視圖之間的數據沒法實時同步, 害我浪費了一個下午.
關於 watchEffect
這個函數的實現和React Hook中的useEffect有異曲同工之妙, 監聽回調函數內依賴的響應式數據的變化來執行回調函數.
對,沒錯, 它能監聽函數內變化的響應數據並且自動執行回調函數! 是不是很魔法! 連反射都做不到監聽函數內依賴的外部變量.
舉個例子:
1const count = ref(0);
2watchEffect(() => console.log(count));
3
4// 當count數據發送變化的時候會執行watchEffect內的回調函數
還有一個watch函數也可以做到類似的操作, 不過需要手動在第一個參數指定監聽的響應式數據. watch的原理就比較容易懂了. 指定了依賴就可以通過掛鉤子來實現監聽變化執行回調了.
問題就在watchEffect是怎麼做到不指定依賴就能知道回調內依賴了哪個響應式數據?並且自動執行的?
這個魔法的原理我想破頭也沒有想出來. 看了一些關於副作用的文章之後才開始理解這個魔法的本質.
watch 和 watchEffect 有一個區別就在於, watchEffect在頁面渲染後會首次執行一次.
這個動作就是魔法的秘密了, 執行後watchEffect就能看到那些響應式數數據收到了回調的影響.(不一定是數據的變化)