本文將分為三個部分:
享受並且讓我知道您在專案中使用的模式和實踐🚀
原文出處:https://dev.to/jacobandrewsky/good-practices-and-design-patterns-for-vue-composables-24lk
我認為了解建置可組合項模式的最佳來源實際上是 Vue.js 文件,您可以在此處查看
Vue 文件顯示了以下 useMouse 可組合項的示例:
// mouse.js
import { ref, onMounted, onUnmounted } from 'vue'
// by convention, composable function names start with "use"
export function useMouse() {
// state encapsulated and managed by the composable
const x = ref(0)
const y = ref(0)
// a composable can update its managed state over time.
function update(event) {
x.value = event.pageX
y.value = event.pageY
}
// a composable can also hook into its owner component's
// lifecycle to setup and teardown side effects.
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
// expose managed state as return value
return { x, y }
}
稍後可以在元件中使用它,如下所示:
<script setup>
import { useMouse } from './mouse.js'
const { x, y } = useMouse()
</script>
<template>Mouse position is at: {{ x }}, {{ y }}</template>
為了獲取資料,Vue 建議使用以下可組合結構:
import { ref, watchEffect, toValue } from 'vue'
export function useFetch(url) {
const data = ref(null)
const error = ref(null)
watchEffect(() => {
// reset state before fetching..
data.value = null
error.value = null
// toValue() unwraps potential refs or getters
fetch(toValue(url))
.then((res) => res.json())
.then((json) => (data.value = json))
.catch((err) => (error.value = err))
})
return { data, error }
}
然後可以在元件中使用它,如下所示:
<script setup>
import { useFetch } from './fetch.js'
const { data, error } = useFetch('...')
</script>
根據上面的示例,以下是所有可組合項都應遵循的約定:
useSomeAmazingFeature.ts
const { x, y } = useMouse()
<script setup>
或 setup()
掛鉤中呼叫。它們也應該在這些上下文中同步呼叫。在某些情況下,您還可以在生命週期掛鉤中呼叫它們,例如“onMounted()”。我已經為我的工作專案和開源專案建置了多個可組合項 - NuxtAlgolia、NuxtCloudinary、NuxtMedusa,因此基於這些,我想根據我的經驗在上面的合同中加入一些要點。
在程式碼標準化的某個時刻,您可能會得出這樣的結論:您希望對可組合項中的狀態保留做出決定。
最容易測試的函數是那些不存儲任何狀態的函數(即它們是簡單的輸入/輸出函數),例如負責將字節轉換為人類可讀值的可組合函數。它接受一個值並返回一個不同的值 - 它不存儲任何狀態。
不要誤會我的意思,你不必做出“或”的決定。您可以完全保留有狀態和無狀態可組合項。但這應該是一個書面決定,以便以後更容易與他們合作 🙂
我們希望使用 Vitest 為我們的前端應用程式實施單元測試。在後端工作時,進行單元測試程式碼覆蓋率非常有用,因為您主要關注邏輯。然而,在前端,您通常使用視覺效果。
因此,我們認為對整個元件進行單元測試可能不是最好的主意,因為我們基本上將對框架本身進行單元測試(如果按下按鈕,檢查狀態是否更改或模式是否打開)。
由於我們已將所有業務邏輯移至可組合項(基本上是 TypeScript 函數)內,因此它們很容易使用 Vitest 進行測試,並且允許我們擁有更穩定的系統。
不久前,在 VueStorefront 中,我們開發了自己的可組合方法(早在它們實際上像這樣被呼叫之前)。在我們的方法中,我們使用可組合項來映射電子商務的業務領域,如下所示:
const { cart, load, addItem, removeItem, remove, ... } = useCart()
這種方法絕對有用,因為它允許將域包裝在一個函數中。在“useProduct”或“useCategory”等更簡單的示例中,實現和維護相對簡單。然而,正如您在此處的“useCart”示例中看到的那樣,當包裝一個包含更多邏輯而不僅僅是資料獲取的域時,這個可組合項正在發展成為一種非常難以開發和維護的形狀。
此時,我開始為 Nuxt 生態系統做出貢獻,其中引入了不同的方法。在這種新方法中,每個可組合項僅負責一件事。因此,我們的想法不是建置一個巨大的“useCart”可組合項,而是為每個功能建置可組合項,即“useAddToCart”、“useFetchCart”、“useRemovefromCart”等。
因此,維護和測試這些可組合項應該更容易 🙂
這將是我的研究的全部內容。如果您想了解有關此主題的更多訊息,請務必查看以下文章: