thumbnail

Vueのライブラリ「VueUse」とは?

VueUseはVueの開発で遭遇する「よくある機能」をロジック単位で切り出し、それを関数として簡単に利用できるライブラリです。この記事ではVueUseの必要性や基本的な使い方、いくつかの関数をピックアップして紹介します。

VueUse概要

VueUseとは

VueUseとは、開発中に出くわす「よくある機能」を、ロジック単位で切り離した関数を提供するライブラリです。
このような関数をコンポジション関数、コンポーザブル関数と言ったりします。
ReactのカスタムHooksのようなものです。

VueUseの例

では、VueUseで用意されている関数の例を挙げます。

例えば、VueUseを使えば、現在のカーソル位置を取得するコードが1行で書けます。
(タグやimportなどで行が増えていますが、ロジック部分は1行です。)

<script setup lang="ts">
import { useMouse } from "@vueuse/core"
const { x, y } = useMouse() 
</script>

このように関数は主にuseXXXXの形式で提供されています。

全関数一覧は公式ドキュメントを御覧ください。

VueUse – Functions(公式ドキュメント)

https://vueuse.org/functions.html#category=Browser

VueUseはComposition APIがベース

VueUseはCompositionAPIで使います。Composition APIについてご存知無い方は次の記事をご参考下さい。

インストール

CDN、NPMの2つを記載します。

・CDN

<script src="https://unpkg.com/@vueuse/shared"></script>
<script src="https://unpkg.com/@vueuse/core"></script>

・npm

npm i @vueuse/core

VueUseの基本情報

関数の戻り値はRef型のオブジェクト

提供されているほとんどの関数の戻り値はRef型のオブジェクトとなっています。
デストラクチャリングして戻り値を得るのがベストプラクティスとされています。

useMouse()の例を見てみます。

<script setup lang="ts">
import { useMouse } from "@vueuse/core"
const { x, y } = useMouse() 
</script>

xとyにデストラクチャリングしており、それぞれの値はRef<number>型となっています。

イベントフィルタ

イベントを制御するフィルターが提供されています。
例えば、throttleFilterはイベントにスロットリングをかけ、debounceFilterはイベントを遅延評価します。

これもまたuseMouseの例で見てみます。

//100ms秒に1回イベントが発火するように抑制
const { x1, y1 } = useMouse({ eventFilter: throttleFilter(100)})

//100ms後にイベントが発火するように抑制
const { x2, y2 } = useMouse({ eventFilter: debounceFilter(100)})

throttleFilterでは100ms秒ごとにマウス位置を取得し、debounceFilterではマウスが停止100ms後にマウス位置が評価されます。

このように、関数に適宜引数を渡すことによって戻り値や動作をカスタマイズすることが出来ます。

レンダリング不要のコンポーネント版もある

useXXXの代わりに<UseXXX>で同様の機能を果たせるコンポーネントが幾つかあります。
useMouseの例をあげます。

<template>
  <UseMouse v-slot="{ x, y }">
    ({{ x }}, {{ y }})
  </UseMouse>
</template>

コンポーネント版を利用するには、別途ライブラリのインストールが必要です。

npm i @vueuse/components

VueUseの関数紹介

それではVueUseのいくつか面白い関数を紹介します。VueUseで提供されている関数は非常に多いです。
今回は全体の極々一部の紹介に留めさせて頂きます。

useBreakpoints

メディアクエリのブレークポイントをプログラマブルに設定できます。
使用手順は次のとおりです。

①ブレークポイントを定義します。
②現在どのブラウザ幅かを判定するブール値の変数を定義します。
③テンプレート側で、②で設定した真偽値をもとに表示を決定します。

以下詳しく説明します。

①では、オブジェクトを利用してブレークポイントを設定します。プロパティ名は自由です。

const breakpoints = useBreakpoints({
  sm: 300,
  md: 600,
  lg: 900
})

②ブラウザ幅を判定する変数を定義します。
①で指定したブレークポイントより小さい(smaller)、2つのブレークポイントの間(between)、大きい(greater)、それぞれを判定する記述をします。以下の変数は真偽値を返します。

const sm = breakpoints.smaller('sm')//より小さい
const md = breakpoints.between('sm', 'md')//間
const lg = breakpoints.between('md', 'lg')//間
const xl = breakpoints.greater('lg')//より大きい

③②で決めた真偽値によって、テンプレートの表示非表示を設定します。

<template>
  <div class="font-mono">
    <div class="wrapper"> sm: <p v-if="sm" >NOW</p></div>
    <div class="wrapper"> md: <p v-if="md" >NOW</p></div>
    <div class="wrapper"> lg: <p v-if="lg" >NOW</p></div>
    <div class="wrapper"> xl: <p v-if="xl" >NOW</p></div>
  </div>
</template>

以下実行例です。

useScroll

スクロールに関する様々な情報を取得できます。
取得できる情報は次のとおりです。

現在のスクロール量 / スクロール中かどうか / ページの一番上(右、下、左)にいるか / スクロールの方向

const el = ref<HTMLElement | null>(null)
const {
  x,  // 横方向のスクロール量
  y, // 縦方向のスクロール量
  isScrolling, // 現在スクロール中か
  arrivedState,  // 左右上下いずれかのページの端にいるか
  directions // スクロールの方向
} = useScroll(el)

//左右上下のそれぞれ端にいるかどうか、boolean
const { left, right, top, bottom } = toRefs(arrivedState)

//スクロールの方向
const { left: toLeft, right: toRight, top: toTop, bottom: toBottom } = toRefs(directions)

useNow

現在時刻を毎秒リアルタイムで更新します。
controlsオプションを付けることで、時刻の一時停止やキャンセルが可能となります。

<script setup lang="ts">
import { useNow } from '@vueuse/core'
const { now, pause, resume } = useNow({ controls: true })
</script>

<template>
  Now: {{ now }} <!--毎秒更新される-->
  <button @click="pause()">Pause</button>
  <button @click="resume()">Resume</button>
</template>

useStorage

リアクティブなLocal / Session Storageを提供します。

<script setup lang="ts">
import { useStorage } from '@vueuse/core'

// オブジェクト登録
const state = useStorage('my-store', { hello: 'hi', greeting: 'Hello' })

// ブール値登録
const flag = useStorage('my-flag', true) // returns Ref<boolean>

// 数字登録
const count = useStorage('my-count', 0) // returns Ref<number>

// セッションストレージの利用、文字列登録
const id = useStorage('my-id', 'some-string-id', sessionStorage) // returns Ref<string>

// 削除
state.value = null
</script>

useBase64

BASE64に変換します。

<script setup lang="ts">
import { useBase64 } from '@vueuse/core'
import { ref, type Ref } from 'vue';
const image = ref() as Ref<HTMLImageElement>
const { base64: imageBase64 } = useBase64(image)
</script>

useCounter

カウンターに必要な機能一式が使えます。(カウント値、カウントアップ、カウントダウン、セット、リセット)

<script setup lang="ts">
import { useCounter } from '@vueuse/core'
const { count, inc, dec, set, reset } = useCounter()
</script>
<template>
  <p>{{count}}</p>
  <button @click="() => inc()">+1</button> 
  <button @click="() => inc(5)">+5</button>
  <button @click="() => dec()">-1</button>
  <button @click="() => set(100)">100</button>
  <button @click="() => reset()">reset</button>
</template>

useCycleList

リストを自動で循環させる機能一式を提供します。

<template>
<div>{{state}}</div>
<button @click="() => prev()">prev</button>
<button @click="() => next()">next</button>
</template>

nextを押せば、あいうえおあいうえおあ….と無限に循環します。

useLastChanged

変数が最後に変更された日時をタイムスタンプ値で返します。
inputと紐付ければ、最後に入力した日時が取得できます。

<script setup lang="ts">
import { useLastChanged } from '@vueuse/core'
import { computed, ref } from 'vue';
const a = ref(0)
const lastChanged = useLastChanged(a)
const time = computed(() => new Date(lastChanged.value))
</script>
<template>
  <input type="text" v-model="a">
  <p>{{time}}</p><!--最後に入力した日時がわかる-->
</template>

その他

全ての関数を知りたい方は公式ドキュメントを御覧ください。(英語です)

VueUse – Functions(公式ドキュメント)

https://vueuse.org/functions.html#category=Browser

更にアドオンでFirebaseやaxios、Cookie、サウンド、モーションなどのコンポジション関数も利用することが出来ます。(余裕があれば別記事で紹介)

まとめ

VueUseとは何かを説明し、その必要性や実際に提供されている関数についていくつか説明しました。
欲しい機能をぜひ見つけて下さい。
公式ドキュメントを読むだけでもコンポーネントの分離方法の勉強になります。