---
# System prepended metadata

title: VueUse
tags: [Vue]

---

# VueUse

## References
+ 🔗 [**VueUse**](https://vueuse.org/)
+ 🔗 [**Composables**][Composables]
+ 🎬 [**Build your own Custom Composables in Vue**](https://youtu.be/bcZM3EogPJE)


## Brief
一個充滿各式 composables 的套件，支援 tree shaking。

## My Opinions
+ 先寫死，除非能算計到是活的或者寫死後非常難改，那就改寫活

## Composables

#### 是個啥
  根據[官方文檔][Composables]，它指的是一段可重用的有狀態邏輯 (<mark>reusable stateful logic</mark>)。
  我覺得其實更像是一種 Design Patterns。

#### 差異
|🔮 <span class="important">IMPORTANT</span>||
|:---|:---|
|Composables|每次 import 後呼叫回傳<mark>不同</mark>物件|
|Pinia|每次 import 後呼叫回傳<mark>相同</mark>物件<br />(單例模式，全域共享的狀態)|

#### 注意

|📘 <span class="note">NOTE</span>|
|:---|
|composables 的檔名和函式應該以 `use` 開頭|


|📘 <span class="note">NOTE</span>|
|:---|
|若 composables 回傳的東西裡有 `reactive`，<br />在 unpacking 時會失去 responsive (所以盡量用 `ref`)。|


|📘 <span class="note">NOTE</span>|
|:---|
|composables 的 [Input Arugments]，<br />應該要盡可能有辦法接受 ref / getter / pure value，<br />即便它們並不需要做到 responsive。<br />你可在 composables 內用 `toValue` 去統一獲得 pure value。|

|📘 <span class="note">NOTE</span>|
|:---|
| 使用 selector 註冊的缺點是無法預先註冊被 v-if 隱藏的元素  |

#### 範例
  ```js
  // mouse.js
  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 }
  }
  ```
  通常我們會把它包起來，供給外部使用
  ```html
  <script setup>
  import { useMouse } from './mouse.js'

  const { x, y } = useMouse()
  </script>

  <template>Mouse position is at: {{ x }}, {{ y }}</template>
  ```

## 紀錄一些有趣的東西

+ **Safe Area**
  原來 mobile 端還有安全區這種東西，難怪 `useMediaQuery` 在 mobile 端總是提前縮
  ![safe area](https://webkit.org/wp-content/uploads/safe-areas-1.png)


[Composables]: https://vuejs.org/guide/reusability/composables.html
[Input Arugments]: https://vuejs.org/guide/reusability/composables.html#input-arguments