有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。
到目前為止,可組合是組織Vue 3應用中業務邏輯的最佳方式。
它們讓你把小塊的邏輯提取到函式中,我們可以輕鬆地重複使用,這樣的程式碼更容易編寫和閱讀。
由於這種編寫Vue程式碼的方式相對較新,你可能想知道在編寫可組合程式碼的最佳做法是什麼。本系列教程將作為一個指南,告訴你如何編寫值得信賴且可靠組合式程式碼。
以下是我們將討論的內容。
- 如何使用選項物件引數來使組合更有配置性
- 使用 ref 和 unref 來使我們的論證更加靈活
- 讓返回值更有用的一個簡單方法
- 為什麼從介面開始會使我們組合會更強大
- 如何使用不需要 await 的非同步程式碼--讓你的程式碼更容易理解
首先, 我們先不看什麼是可組合式?
什麼是可組合式?
根據Vue文件,可組合是 "利用Vue Composition API來封裝和重用有狀態邏輯的函式"。
這意味著任何使用響應式的程式碼都可以變成一個可組合的。
下面是一個來自Vue.js文件的useMouse可組合的簡單例子。
import { ref, onMounted, onUnmounted } from 'vue'
export function useMouse() {
const x = ref(0)
const y = ref(0)
function update(event) {
x.value = event.pageX
y.value = event.pageY
}
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
return { x, y }
}
我們將狀態定義為 refs
,然後在滑鼠移動時更新該狀態。通過返回x
和y
refs,我們可以在任何元件(甚至是另一個可組合的元件)中使用它們。
下面是我們如何在一個元件中使用這個可組合的。
<template>
X: {{ x }} Y: {{ y }}
</template>
<script setup>
import { useMouse } from './useMouse';
const { x, y } = useMouse();
</script>
正如你所看到的,使用 useMouse
組合就可以重複使用所有這些邏輯。只需很少的額外程式碼,我們就能在我們的元件中抓取滑鼠座標。
選項物件引數
大多數可組合程式有一個或兩個必要的輸入。然後有一系列的可選引數來幫助配置可組合的工作方式。
當配置你的可組合的時候,你可以傳入一個選項物件,而不是傳入一長串的引數,。
// 使用一個選項物件
const title = useTitle('A new title', { titleTemplate: '>> %s <<' });
// Title is now ">> A new title <<"
// 使用入一長串的引數
const title = useTitle('A new title', '>> %s <<');
// Title is now ">> A new title <<"
將選項作為一個整體物件而不是引數傳入,給我們帶來一些好處。
首先,我們不需要記住引數的正確順序。現在有了TypeScript和編輯器自動完成功能,這已經不是一個問題了,但它仍然有區別。對於一個Javascript物件,鍵的順序並不重要。
第二,程式碼更易讀,因為我們知道這個選項是做什麼的。程式碼即註釋。我們不需要在原始碼中尋找,也不需要依靠我們的IDE來讓我們知道。
第三,以後再新增新的選項就容易多了。這既適用於向可組合本身新增新選項,也適用於在使用可組合時新增選項。
所以,使用一個選項物件會更好。但我們如何實現呢?
以可組合的方式實施
下面是如何在一個可組合的中實現選項物件模式。
export function useMouse(options) {
const {
asArray = false,
throttle = false,
} = options;
// ...
};
在這裡,如果引數是必需的,我們可以接受一兩個引數,然後最後一個引數是選項物件。所以在這個例子中,useMouse
沒有必要的引數,只有選項物件。
下一步是分解選項物件。通過解構,我們可以訪問所有的值,並明確地為每個可能的選項提供預設值。
現在,我們將看看VueUse中的兩個不同的組合是如何應用該模式的。VueUse是Vue 3的一個開源組合集合,編寫得非常好。它是學習如何編寫可組合程式碼的一個很好的資源
https://vueuse.org/
首先,我們看看useTitle
,然後再看看useRefHistory
是如何工作的。
useTitle
useTitle是一個相當簡單的組合。它用來更新頁面的標題。
const title = useTitle('Initial Page Title');
// Title: "Initial Page Title"
title.value = 'New Page Title';
// Title: "New Page Title"
它也有幾個選項以獲得額外的靈活性。
可以提供一個 titleTemplate
,還可以設定它來觀察(observe)其他指令碼可能做出的任何改變的標題(使用MutationObserver)。
const titleOptions = {
titleTemplate: '>> %s <<',
observe: true,
};
下面是使用選項物件的方式:
const title = useTitle('Initial Page Title', {
titleTemplate: '>> %s <<',
observe: true,
});
// Title: ">> Initial Page Title <<"
title.value = 'New Page Title';
// Title: ">> New Page Title <<"
當你檢視useTitle的源碼時,它是這麼做的:
export function useTitle(newTitle, options) {
const {
document = defaultDocument,
observe = false,
titleTemplate = '%s',
} = options;
// ...
}
useTitle
可組合式有一個必要的引數,然後是一個 options
物件。在這之後,它完全按照這裡描述的模式實現其餘部分。
現在讓我們看看一個稍微複雜的可組合,它也使用這個選項物件模式。
useRefHistory
useRefHistory
更有趣一些。它可以讓你跟蹤對一個 ref
所做的所有改變,可以容易地執行撤銷和重做操作。
// Set up the count ref and track it
const count = ref(0);
const { undo } = useRefHistory(count);
// Increment the count
count.value++;
// Log out the count, undo, and log again
console.log(counter.value); // 1
undo();
console.log(counter.value); // 0
此可組合可採用許多不同的選項
{
deep: false,
flush: 'pre',
capacity: -1,
clone: false,
// ...
}
我們可以把選項物件作為第二個引數傳入,以進一步配置這個可組合的行為方式,與我們之前的例子一樣。
const state = ref({});
const { undo, redo } = useRefHistory(state, {
deep: true, // 追蹤物件和陣列內部的變化
capacity: 15, // 限制我們追蹤的步驟數量
});
如果我們看一下這個原始碼,我們會發現它使用了與useTitle
完全相同的物件重構模式。
export function useRefHistory(source, options) {
const {
deep = false,
flush = 'pre',
eventFilter,
} = options;
// ...
}
然而,在這個例子中,我們只在開始時從選項物件中抽出幾個值。
這是因為useRefHistory
在內部依賴於useManualRefHistory
可組合程式。其餘的選項將作為該可組合的選項物件在後面的可組合中傳遞。
// ...
const manualHistory = useManualRefHistory(
source,
{
// Pass along the options object to another composable
...options,
clone: options.clone || deep,
setSource,
},
);
// ...
把所有的東西集中起來
本文是我們“編寫更好的組合”系列的第一部分。
我們研究瞭如何將一個選項物件作為引數新增到元件中,從而使元件的可配置性大大增強。例如,你不需要擔心引數的排序,也不需要記住每個引數的作用,而且向一個物件新增更多的選項要比更新傳入的引數容易得多。
但我們並不只是看了這個模式本身。我們還看到了VueUse的組合物 useTitle
和useRefHistory
是如何實現這一模式的。他們的方式略有不同,但由於這是一個簡單的模式,你可以做的變化不多。
本系列的下一篇文章將探討我們如何接受Refs和常規Javascript值作為引數。
// 傳遞一個 ref 值,可以工作
const countRef = ref(2);
useCount(countRef);
// 或者只給一個簡單的數字
const countRef = useRef(2);
這增加了靈活性,允許我們在應用程式的更多情況下使用組合。
編輯中可能存在的bug沒法實時知道,事後為了解決這些bug,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。
作者:Michael Thiessen 譯者:小智 來源:vuemastery
原文: https://www.vuemastery.com/bl...
交流
有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。