一、使用reactive函數聲明數組如何正確賦值
需求:將接口請求到的列表數據賦值給響應數據 array
const arr = reactive([]); const load = () => { const res = [2, 3, 4, 5]; //假設請求接口返回的數據 // 方法1 失敗,直接賦值丟失了響應性 // arr = res; // 方法2 這樣也是失敗 // arr.concat(res); // 方法3 可以,但是很麻煩
res.forEach(e => { arr.push(e); }); };
問題原因:這是因為 arr = newArr
這行代碼讓arr失去了響應式。vue3 使用proxy
,對於對象和數組都不能直接整個賦值。
具體原因:reactive聲明的響應式對象被 arr 代理,操作代理對象需要有代理對象的前綴,直接覆蓋會丟失響應式。
方法2為什么不行?只有push或者根據索引遍歷賦值才可以保留reactive數組的響應性?如何方便的將整個數組拼接到響應式數據上?下面我們看下解決方案:
// 這幾種辦法都可以觸發響應性,推薦第一種 // 方案1:創建一個響應式對象,對象的屬性是數組
const state = reactive({ arr: [] }); state.arr = [1, 2, 3] // 方案2: 使用ref函數
const state = ref([]) state.value = [1, 2, 3] // 方案3: 使用數組的push方法
const arr = reactive([]) arr.push(...[1, 2, 3])
二、script setup 語法糖中reactive + toRefs+解構如何優雅呈現
比如下面這樣,我定義了一個 reactive() 聲明的對象,想在模板上響應式的使用其值,如果不使用 setup 語法糖,就可以使用 toRefs 然后配合解構 return 出去。使用 setup 語法糖的話,就可以這樣
let starData = reactive({ total: 0, stars: Array<Star>(), }) const { total, stars } = toRefs(starData)
三、Options API 與 Composition API 如何選擇及混用是否對性能有影響
1、使用了 Vue3,是否都要遵循用 Composition API 的形式去寫頁面?
答案是否定的。
需要注意一點:Vue3 並沒有廢棄 Options API,甚至還會全力支持兼容 Vue2 語法的工作。
而 CompositionAPI 出現的背景主要是為了解決邏輯抽象和和復用的問題,但不意味着它成為了 Vue3 的標准。
因此如何區分場景使用 Options API
or Composition API
主要看業務邏輯的復雜程序,例如一些簡單的 toast/button 等基礎組件,用options API
形式會更加清晰和簡潔。而相對復雜的業務邏輯,可以用 Composition API
,可以把單獨一塊邏輯抽離到一個模塊,通過 hook 函數的方式去解決。
2、Vue3 中混用 Options API 和 Composition API 會不會對性能產生影響?
答案是不會。其實從問題 1 就可以明顯地看出來並不會對性能產生任何影響。不應該被option api
限制思維,而更多關注邏輯內聚問題。
四、關於 setup 中沒有 this 的問題及 setup 的執行時機
vue 官方文檔是這么解釋的:在 setup() 內部,this 不會是該活躍實例的引用,因為 setup()
是在解析其它組件選項之前被調用的,所以 setup()
內部的 this 的行為與其它選項中的 this 完全不同。這在和其它選項式 API 一起使用 setup() 時可能會導致混淆。這意味着,除了 props 之外,你將無法訪問組件中聲明的任何屬性 —— 本地狀態,計算屬性/方法。
但是從源碼實現你會發現其實組件實例創建在前,函數之所以訪問不到 this,是因為它在執行 setup 函數的時候,就沒有把組件實例 instance 傳給 setup。也沒有把 this 指向實例 instance。
因此執行順序其實是:組件實例創建在 setup 函數執行之前,但是 setup 執行的時候,組件還沒有 mounted,而晚於 beforeCreate 鈎子,早於 create 鈎子。