---
# System prepended metadata

title: "共筆 - 2025/8/17 Tech Book Community 線下小聚 in 台北 - 【ILya】 一起探索 VueUse 背後的黑魔法 \U0001FA84"

---

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