Vue 3 實戰:從零到一封裝一個 useMouse Composable
在 Vue 3 中,將元件邏輯「去中心化」是保持程式碼整潔的關鍵。今天我們以常見的 滑鼠座標監聽 為例,示範如何從傳統的元件件寫法,重構成靈活的 Composable 函數。
初始狀態:在單一元件 (SFC) 中撰寫
通常我們會直接在 App.vue 寫入監聽邏輯。雖然功能正常,但若其他元件也需要同樣的功能,就必須複製貼上,這違反了 DRY (Don't Repeat Yourself) 原則。
vue
// App.vue
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
const x = ref(0);
const y = ref(0);
function update(e) {
x.value = e.pageX;
y.value = e.pageY;
}
onMounted(() => {
window.addEventListener("mousemove", update);
});
onUnmounted(() => {
window.removeEventListener("mousemove", update);
});
</script>
<template>
<p>Mouse Position: {{ x }}, {{ y }}</p>
</template>進階重構:封裝成可重複使用的邏輯函數
為了達到多元件共享,我們根據 Composable 的設計規範,在 composables 目錄下建立專屬檔案,並以 use 開頭命名。
實作 useMouse.js
核心邏輯保持不變,但我們將狀態與行為封裝在函數中,並 回傳 需要暴露給外部使用的響應式屬性。
js
// composables/useMouse.js
import { ref, onMounted, onUnmounted } from "vue";
export default () => {
const x = ref(0);
const y = ref(0);
function update(e) {
x.value = e.pageX;
y.value = e.pageY;
}
onMounted(() => {
window.addEventListener("mousemove", update);
});
onUnmounted(() => {
window.removeEventListener("mousemove", update);
});
return { x, y };
};最終成果:在元件中優雅呼叫
重構後的元件變得極度簡潔,所有的複雜邏輯都被抽離到 useMouse 之中,元件只負責讀取數據與渲染 UI。
vue
// App.vue
<script setup>
import useMouse from "@/composables/useMouse";
const { x, y } = useMouse();
</script>
<template>
<p>Mouse Position: {{ x }}, {{ y }}</p>
</template>核心要點筆記
獨立狀態
每一個引用 useMouse 的元件,都會擁有自己獨立的 x 與 y 狀態。即使在不同元件中同時使用,數據也不會相互干擾或衝突。
清理機制
將 onUnmounted 封裝在 Composable 內部,確保了當元件銷毀時,監聽器會自動移除,有效防止記憶體洩漏 (Memory Leak)。
高可讀性
透過解構賦值,我們可以一眼看出元件使用了哪些外部邏輯,提升了大型專案的可維護性。
