Vue 處理共用邏輯的方式
以往用 Vue2 處理共用邏輯有幾種方式
🔸 Mixins
🔸 Higher-order Components ( HOC )
🔸 Renderless Components
但 Vue2 存在著一些問題,命名衝突、產生多餘的元件實體、資料難以追蹤來源,就會有一些狀況產生。
隨著 Vue3 的升級,Vue3 Composition API 解決了 Vue2 的問題
🔸 資料追蹤清晰
🔸 不會有命名衝突的問題
🔸 不需要產生多餘的元件
取得 Composition API 的值
從共用邏輯封裝的 Composition API 取值
範例: 顯示滑鼠座標
封裝邏輯的 JS
不同 components 可能會共用的 JS
composition-api/useMousePosition.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import { onMounted, onUnmounted, ref } from "vue"; export function mousePosition() { const x = ref(0); const y = ref(0); const positionUpdate = (e) => { x.value = e.pageX; y.value = e.pageY; }; onMounted(() => { window.addEventListener("mousemove", positionUpdate); }); onUnmounted(() => { window.removeEventListener("mousemove", positionUpdate); }); return { x, y }; }
|
整合封裝好的 JS
所有封裝的 JS 都在 index.js 做整合,component 只需引入這支就好
composition-api/index.js
1 2
| import { mousePosition } from "./useMousePosition.js"; export const useMousePosition = mousePosition;
|
index.js 引入到 component
MousePosition.vue
1 2 3 4 5 6 7
| import { useMousePosition } from "@/composition-api"; export default { setup() { const { x, y } = useMousePosition(); return { x, y }; }, };
|
1 2 3 4
| <div class="box"> <h1>Mouse Position</h1> <h2>x: {{x}} y: {{y}}</h2> </div>
|
解構取出 reactive 的物件
組件透過解構要取出 reactive 的物件時,解構出來的變數會變成單純的變數(不具備綁定功能),要讓 reactive 的變數被綁定有兩種方法:
1️⃣ 不使用解構,直接 return reactive 物件
composition-api/useMousePosition.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import { onMounted, onUnmounted, reactive, ref } from "vue"; export function mousePosition() { const position = reactive({ x: 0, y: 0, }); const positionUpdate = (e) => { position.x = e.pageX; position.y = e.pageY; }; onMounted(() => { window.addEventListener("mousemove", positionUpdate); }); onUnmounted(() => { window.removeEventListener("mousemove", positionUpdate); }); return position; }
|
MousePosition.vue
1 2 3 4 5 6 7
| import { useMousePosition } from "@/composition-api"; export default { setup() { const position = useMousePosition(); return { position }; }, };
|
1 2 3 4
| <div class="box"> <h1>Mouse Position</h1> <h2>x: {{ position.x }} y: {{ position.y }}</h2> </div>
|
2️⃣ 使用 toRefs
只要把 reactive 物件用 toRefs 包起來,就可以讓解構的值具備資料綁定的效果
composition-api/useMousePosition.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import { onMounted, onUnmounted, reactive, ref, toRefs } from "vue"; export function mousePosition() { const position = reactive({ x: 0, y: 0, }); const positionUpdate = (e) => { position.x = e.pageX; position.y = e.pageY; }; onMounted(() => { window.addEventListener("mousemove", positionUpdate); }); onUnmounted(() => { window.removeEventListener("mousemove", positionUpdate); }); return toRefs(position); }
|
MousePosition.vue
1 2 3 4 5 6 7
| import { useMousePosition } from "@/composition-api"; export default { setup() { const { x, y } = useMousePosition(); return { x, y }; }, };
|
1 2 3 4
| <div class="box"> <h1>Mouse Position</h1> <h2>x: {{x}} y: {{y}}</h2> </div>
|
🔡 如要 return 更多的變數可使用展開運算子的方式
useMousePosition.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import { onMounted, onUnmounted, reactive, ref, toRefs } from "vue"; export function mousePosition() { const name = ref("bobee"); const position = reactive({ x: 0, y: 0, }); const positionUpdate = (e) => { position.x = e.pageX; position.y = e.pageY; }; onMounted(() => { window.addEventListener("mousemove", positionUpdate); }); onUnmounted(() => { window.removeEventListener("mousemove", positionUpdate); }); return { ...toRefs(position), name }; }
|
MousePosition.vue
1 2 3 4 5 6 7
| import { useMousePosition } from "@/composition-api"; export default { setup() { const { x, y, name } = useMousePosition(); return { x, y, name }; }, };
|
1 2 3 4
| <div class="box"> <h1>Mouse Position</h1> <h2>x: {{x}} y: {{y}} {{ name }}</h2> </div>
|
這麼一來就可以取出多個值了!
設定 Composition API 的值
範例: 點擊按鈕改變值
useState.js
1 2 3 4 5 6 7 8 9
| import { ref } from "vue";
export function stateAdd() { const idx = ref(0); const addState = () => { idx.value++; }; return { idx, addState }; }
|
index.js
1 2 3 4 5
| import { mousePosition } from "./useMousePosition.js"; import { stateAdd } from "./useState.js";
export const useMousePosition = mousePosition; export const useState = stateAdd;
|
1 2 3 4 5 6 7
| import { useState } from "@/composition-api"; export default { setup() { const { idx, addState } = useState(); return { idx, addState }; }, };
|
1 2 3 4
| <div class="block"> <h1>number: {{idx}}</h1> <button @click="addState">add</button> </div>
|
封裝的內容都是 priviate 的,即使複製兩個 components 也不會影響到各別的值
封裝非同步處理的狀態
useFetch.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import { reactive, ref } from "vue"; import axios from "axios";
export function fetchs(API_url = "") { const isLoad = ref(false);
const fetchData = reactive({ data: [] });
const errorMsg = ref("");
axios .get(API_url) .then((res) => { isLoad.value = true; fetchData.data = res.data; }) .catch((error) => { isLoad.value = true; errorMsg.value = error.request.statusText; }); return { isLoad, fetchData, errorMsg }; }
|
index.js
1 2 3 4 5 6 7
| import { mousePosition } from "./useMousePosition.js"; import { stateAdd } from "./useState.js"; import { fetchs } from "./useFetch.js";
export const useMousePosition = mousePosition; export const useState = stateAdd; export const useFetch = fetchs;
|
FetchData.vue
1 2 3 4 5 6 7 8 9
| import { useFetch } from "@/composition-api"; export default { setup() { const { isLoad, fetchData, errorMsg } = useFetch( "https://vue-lessons-api.herokuapp.com/photo/list" ); return { isLoad, fetchData, errorMsg }; }, };
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| <div> <img v-if="!isLoad" class="loading" src="../assets/load.gif" alt="" /> <h1 v-if="errorMsg">ERROR: {{ errorMsg }}</h1> <div v-if="isLoad" class="imgBlock"> <img v-for="item in fetchData.data" :key="item.url" :src="item.url" alt="" /> </div> </div>
|
以上是我的學習筆記,希望也有幫助到你哦 😀
🚀實體工作坊分享
最近時賦學苑開了實體體驗課,即使你對程式碼沒有概念也能上手!Lala 會帶你一起做出一個個人品牌形象網站,帶你快速了解前端的開發流程,快跟我們一起玩轉 Web 吧!
🚀線上課程分享
線上課程可以加速學習的時間,省去了不少看文件的時間XD,以下是我推薦的一些課程
想學習更多關於前後端的線上課程,可以參考看看。
Hahow 有各式各樣類型的課程,而且是無限次數觀看,對學生或上班族而言,不用擔心被時間綁住
如果你是初學者,非常推薦六角學院哦!
剛開始轉職也是上了六角的課,非常的淺顯易懂,最重要的是,隨時還有線上的助教幫你解決問題!
Udemy 裡的課程非常的多,品質普遍不錯,且價格都滿實惠的,CP值很高!
也是很多工程師推薦的線上課程網站。