VueUseについて調べてみました

この記事は弁護士ドットコム Advent Calendar 2020、11日目の記事です。  

こんにちは、弁護士ドットコムのフロントエンドエンジニア たか（ @happylifetaka ）です。  
昨日は、@koriym さんの「[メディアタイプとALPSプロファイル](https://qiita.com/koriym/items/2e928efb2167d559052e)」でした。
ドメイン固有のメディアタイプ、プロファイルのどちらも詳しく説明されています。👀

さて、フロントエンドエンジニアチームは毎週Javascript関連のプチ勉強会をしています。今回はそのプチ勉強会で使用した「VueUseについて調べてみました」の記事を紹介します。
実は、Qiitaに初投稿ですのでお手柔らかによろしくお願いいたします。

# VueUseとは？
VueUseとは、react-use( https://github.com/streamich/react-use )にインスパイアされたVueのComposition API集です。
  
以下の特徴があります。　（公式サイトより）
- 依存関係0なので、バンドルのサイズは心配なし
- Fully tree shakable(不要な部分を除去してバンドルしてくれる）
- Typescriptで記述されている
- Vue Demiを使用しており、Vue3,Vue2のどちらもサポート
- StoryBookで、インタラクティブなドキュメントとデモを掲載
- CDNを介しての使用可
- オプションアドオンとしてFirebase、vue-i18nをサポート
- MITライセンス

# example（サンプルコード）
マウスの座標とユーザーがダークモードを使用しているかどうか。

``` javascript
import { useMouse, usePreferredDark, useLocalStorage } from '@vueuse/core'

new Vue({
  setup() {
    // ユーザーのマウスの座標を取得します。
    const { x, y } = useMouse()

    // ユーザーがダークモードを使用しているか取得します。
    const isDark = usePreferredDark()
    return { x, y, isDark }
  }
})
```

[サンプル(CODEPEN)](https://codepen.io/happylifetaka/pen/VwaaWPX)
CODEPEN で書きましたが、公式のstorybook でdemoを実行できるので、そちらを見ればOKです。

# どんなことができるの？
いろんなことができます。具体的には以下です。（流し見推奨）

## アニメーション関係
- `useInterval` 一定ms秒ごとに増加するカウンタ

``` javascript
      const { counter } = useInterval(200)
```
- `useIntervalFn` setIntervalをラッピングしたもの
    
``` javascript
      const { start, stop } = useIntervalFn(() => {
      counter.value++ }, 1000)
```

- `useNow` 現在のタイムスタンプを返してくれる

``` javascript
      const now = useNow()
```

- `useRaf` requestAnimationFrameの反応経過時間を返してくれる
 
``` javascript
       const elapsed = useRaf()
```

- `useRafFn` requestAnimationFrameの反応経過時間ごとに実行する関数を作る
   
``` javascript
useRafFn((elapsed) => {
  console.log(elapsed.value)
})
```

- `useTimeout` 一定時間後に処理を実行（startがtrueになる）

``` javascript
const { ready, start } = useTimeout(1000)
```

- `useTimeoutFn` useTimeoutの関数版

``` javascript
const { ready, start } = useTimeoutFn(() => {
  console.log('Fired!')
}, 3000)
```

- `useTransition` 様々なトランジションの変化に掛かる時間を取得する
    - トランジションって何って方はこちらを参照 
        - https://vueuse.js.org/?path=/story/animation--usetransition

## ブラウザ関係
- `useBrowserLocation`  browser location(hostname...etc)を取得する。
- `useClipboard` クリップボードの設定・取得をする。（とあるがChrome上で、公式のStorybookでは取得が同一画面でしか動かない。）
- `useCssVar`要素のCssを操作する。
-  `useEventListener` イベントリスナーを設定する。（addEventListenerのラッピング、removeも自動でしてくれる）
- `useFullscreen` フルスクリーンかを取得する。またフルスクリーンと解除の関数も取得。
- `useMediaQuery`大きな画面かとダークモードかを取得する。

``` javascript
const isLargeScreen = useMediaQuery('(min-width: 1024px)')
```

- `usePermission`位置情報、マイク、カメラ、MIDIのパーミッションを取得する。
- `usePreferredColorScheme` ダークモードかライトモードか指定なしかを取得する。
- `usePreferredDark`ダークモードか取得する。
- `usePreferredLanguages`ブラウザの優先言語を取得する。
- `useShare`  Web Share APIを呼び出してシェアを行う（Safariとスマホのブラウザでしか動作しない）
- 感知（センサー）関係
- `useBattery`バッテリーの状態（%,充電中かなど）
- `useDeviceLight`光センサーの明るさを取得する
- `useDeviceMotion`モーションセンサーの数値を取得
- `useDeviceOrientation`デバイスの物理的方向を取得する（スマホ向け）
- `useDocumentVisibility`ブラウザを最小化やタブで切り替えて離れてから戻ったかを取得する。
- `useElementVisibility`要素がviewport内に入ってるかを取得する
- `useGeolocation` Geolocation APIを使って位置情報を取得する
- `useMouse` マウスの座標取得する。
-  `useMouseInElement`要素内のマウスの座標を詳細で取得する。
- `useNetwork`ネットワークの状態(オンライン、ダウンロード速度、3Gや4Gなど）を取得する。
- `useOnline` オンラインかどうかを取得する
- `usePageLeave`ページをはなれたかどうか取得する
- `useParallax`視差（パララックス）効果を作成する。
- `useWindowScroll` ウィンドウのスクロール位置を取得する。
- `useWindowSize`ウィンドウサイズを取得する。

## State(状態)関係  

- `createGlobalState`Vueインスタンス全体で利用できるStateを作成する
-  `useAsyncState` ブロッキングされない非同期のstateを作成する。(例:ajaxなどの読み込みが終わったら反映される）
-  `useCounter` カウンターを取得、設定する。
- `useIdle` ユーザーが一定時間非アクティブかを取得する。
- `useLocalStorage` LocalStorageの値を取得する
-  `useSessionStorage` SessionStorage. の値を取得する
-  `useStorage` LocalStorage/SessionStorageに値を設定したり取得する
-  `useStoragePlain` 非推奨 useStorageを使ってください。（多分旧ライブラリ？）
 
## Side Effect（副作用）関係

- `useDebounce` 一定時間後に引数に指定されたrefを返す。(一定時間後に検索とかで便利そう。)
 
``` javascript
const input = ref('');
const debounced = useDebounce(input, 1000);
```

- `useDebounceFn` useDebounceの関数版
- `useThrottle` (入力されて変化があっても)一定時間毎しかrefを返さない。
          （例：1000ms秒の間に入力値が変化してもrefが返るのは1回)
- `useThrottleFn` useThrottleの関数版
        
## その他
- `useWebSocket` webSocketに接続してデータを取得と送信を行う
- `useWebWorker` Web Workers に接続してデータの取得と送信を行う。
- `useWebWorkerFn` UIをブロッキングしない処理を実行するworkerを作る。
   
## アドオン関係
- `Firebase` FirebaseのFirestoreとRTDBから取得ができる（ローカルデータとリモートデータベースの同期を常に維持することは簡単との説明あるがおそらく書き込みはできない）
- `vue-i18n` 多言語対応のライブラリi18nをラッピングしたもの。
   
## 所感
- バンドルファイルがない、Vue3,Vue2の両方とも対応しているのは素晴らしい。
- リアクティブに値を取得（や設定）できるのは便利。
- ライブラリの使用が想像以上に簡単。
- 多くの機能がありいろんなことができる。一部用途がニッチな機能もあるが、個人開発とかプロトタイプ作成でも使いやすそう。
- 基本的にブラウザのAPIをラッピングしてるもので、IEとか特定のブラウザで動かないものもある。
- ソースは読みやすいものも多いので気になる機能があればソースを読みに行き実装方法を知るのも手。

## クラウドサイン でのVue.js状況について
VueUse は使用していないですがクラウドサインではVue.jsを使用しています。
しかし、レガシーなコードもあり徐々にjQueryからVue.jsへ移行作業を進めています。
興味がある方は以下へ。

Vue.js経験者求む！クラウドサインのモダン化をリードしてください！
https://www.wantedly.com/projects/538325

## 12/12はPHPCon(Vue.jsではないですが…)
実は、PHPカンファレンスのスタッフもしているので少し宣伝です。
PHPカンファレンス2020が今年はオンライン開催で2020/12/12の明日開催です。
参加費は無料ですので、興味ある方は是非。
https://phpcon.php.gr.jp/2020/

# 明日(12/12)の記事は…
 明日(12/12)の記事は、 @michimani さんの「AWS CLI のみで何か構築する話」です。お楽しみに。