# 2025/8/17 Tech Book Community 線下小聚 in 台北 - 【ILya】 一起探索 VueUse 背後的黑魔法 🪄 ::: info Slido: https://app.sli.do/event/h2q9s6czM3dqrHtDhC4Lsf 會後回饋表單:https://forms.gle/Vvmo7AByC4GfYNSH9 9 月「後端里長伯」小聚調查:https://forms.gle/mvkqA9NQz7X2V55YA 簡報:https://talks.ilyal.me/2025/tbc-vueuse-magic [Alexander Litcher Youtube](https://www.youtube.com/watch?v=HaeNQXJ-sgs) ::: ### Composables 組合式函數 ```javascript= <script setup> import { ref, onMounted, onUnmounted } from 'vue' 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)) </script> <template>Mouse position is at: {{ x }}, {{ y }}</template> ``` ```javascript= 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 } } ``` ```javascript= import { onMounted, onUnmounted } from 'vue' export function useEventListener(target, event, callback) { // if you want, you can also make this // support selector strings as target onMounted(() => target.addEventListener(event, callback)) onUnmounted(() => target.removeEventListener(event, callback)) } ``` ```javascript! import { ref } from 'vue' import { useEventListener } from './event' export function useMouse() { const x = ref(0) const y = ref(0) useEventListener(window, 'mousemove', (event) => { x.value = event.pageX y.value = event.pageY }) return { x, y } } ``` * tree-shake * typescript * 支援cdn * ssr支援(nuxt) * 生態系豐富 也可以透過 component 來使用(@vueuse/component) 可以透過重載的方式 ```typescript= export function useToggle<Truthy, Falsy, T = Truthy | Falsy>(initialValue: Ref<T>, options?: UseToggleOptions<Truthy, Falsy>): (value?: T) => T export function useToggle<Truthy = true, Falsy = false, T = Truthy | Falsy>(initialValue?: T, options?: UseToggleOptions<Truthy, Falsy>): [ShallowRef<T>, (value?: T) => T] ``` 使用 tryOnMounteed 和tryOnUnmounted 來避免在元件以外的地方執行時出錯 tryOnScipeDispose 底層版的 unmounte watchImmediate 回傳一個 watch, 只是參數寫死 - watchOnce - watchDeep(deep 是可以傳入數字的,代表要監聽到第幾層) - watchWithFilter 什麼情況下不要監聽 - watchTriggerable 彈性調整觸發時機 - watchPausable - watchIgnorable ### 副作用清理 * watch * addEventListener * Web API ### shallowRef 後端回傳的資料、error 可以使用 shallowRef, shallowRef 只對物件和陣列有用,若是 string, number 還是會被解析為 ref ### Readonly vue3 裡的 API,昂。對於不應該改的東西,使用 readOnly,當嘗試修改時還是可以改,但會出現 vue warn ### getCurrentInstance Vue3 裡的 API。讀取當前組建實例和資訊,例如被渲染後的 DOM useTemplateRef: vue3.5+ 才可用 ### VueUse 解決了什麼問題 ⭕️ 開箱即用(提供許多現成的組合式函式) ⭕️ 關注點分離(將業務邏輯抽離,隱藏實作細節) ⭕️ 迭代更新(讓你在 vue2/3 都可以使用,但要注意的是 vue2 必須使用 VueUse v12 以前的版本) ⭕️ 最佳實踐(學習如何撰寫組合式函數) ⭕️ 安全可靠(大量用戶使用,撰寫大量測試) ⭕️ 生態系豐富(全家桶服務,讓你 vueuse 打天下) PS. React 的朋友可以用 ReactUse https://www.bilibili.com/video/BV1x54y1V7H6/ > 貢獻開源沒有你想像中那麼困難,就像是公司的一個小專案 ### QA 貢獻開源專案管道 1. 找剛出來的(可以追蹤 AF, 他很常寫新的包) 2. 找沒什麼人貢獻的 3. 找你有在用的 vue3.3 之後的版本建議可以更新最新的 vueUse 版本