# 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 版本