【Vue.js 3】書籍等にはあまり載ってなかった（と思う）こと5つ

## はじめに
先日、とある EC サイトを Vue 3 を使って実装しリリースしました。機能の一部を Vue で書いた経験はあったのですが、アプリケーション全体を JS フレームワークで実装したのは初めてでした。

Vue 2 の書籍は 1 冊読んだことがありましたが、Vue 3 は初めて使うので、念の為、Vue 3　対応のものを案件スタート前に 1 冊読みました。

ちなみに書籍はこちらです。
- [改訂2版 基礎から学ぶVue.js [2.x対応! ]](https://www.amazon.co.jp/dp/4863543239/ref=cm_sw_em_r_mt_dp_JKJ6ZK541SM3FWVPBEDE)
- [Vue.js3超入門](https://www.amazon.co.jp/dp/4798063738/ref=cm_sw_em_r_mt_dp_8DRJ9B0YG2H48WD4F7X0)

しかし、いざ開発を初めてみると「あれ！？これってどうやればいいんだ？」と調べたり、試したりしたことがいくつかありましたので、そこから 5 つの Tips をまとめておきたいと思います。これから Vue.js を学ぶ、実装するという方のお役に立てれば幸いです。

ただ、各プロジェクトの環境に左右される部分もありますので、どのような状況で発生したかは記載しましたが、伝わりづらい場合はコメントいただければ回答いたします。

## 1. コンポーネントに CSS 設計における Modifier を渡したい
### 利用シーン
- SFC（単一ファイルコンポーネント）利用しているとき
- SFC の外で CSS 設計していて、コンポーネントごとに別のクラス名（Modifier）を設定したいとき

```vue:Parent.vue
<template>
  <child modifier="child__large child__warning"></child>
</template>

<script>
import Child from './Child';
export default {
  components: {
    Child,
  },
}
</script>
```
```vue:Child.vue
<template>
  <div :class="['child', modifier]">
  // コンテンツ
  </div>
</template>

<script>
export default {
  props: {
    modifier: String,
  },
}
</script>
```
今回 CSS 設計は FLOCSS を参考にした別ディレクトリで管理していましたので、このようなケースが発生しました。
このような場合は props で値を受け渡して、class を bind させればいいですね。
Child.vue で設定しておきたいクラス名がある場合は、上記のような形で配列にしておけばいいですし、条件によってクラスを付け外しする場合はオブジェクトにするケースもあります。

また、SFC 内で CSS が完結していると記述は変わってくると思いますし、カプセル化された Web Components を導入する場合の CSS 設計は面白そうなテーマです。Web Components については、弊社のアドベントカレンダーで後日掲載予定の Topic となっておりますのでお楽しみに。

## 2. 各ページの HTML ファイルが存在している環境で、全体をひとつのアプリケーションとして機能させたい
### 利用シーン
- 各ページの HTML ファイルが存在しているとき（ Vue-CLI や Vite などを利用していない）
- 各ページで選択した情報を引き継いで、全体をひとつのアプリケーションとして動かしたいとき

各ページの HTML ファイルが存在していると、ページ遷移するたびに JS ファイルが初期化されます。
そのためページ間で情報を引き継ぐには、以下のような選択をすることになると思います。

1. URL パラメータで情報を受け渡す
2. 選択した内容などをすべて API などでサーバに送り、ページ遷移後はロード時に必要な情報を取得する
3. localStorage や sessionStorage に情報を保存しておく

今回私は 3 の localStorage に保存しておくことにしました。
それを実現するために、状態管理ライブラリである [Vuex](https://vuex.vuejs.org/ja/) と、Vuex の state を localStorage に保管してくれる [vuex-persistedstate](https://github.com/robinvdvleuten/vuex-persistedstate) というプラグインを利用します。これらのパッケージの使い方は各ドキュメントを参照いただければと思います。

## 3. vuex-persistedstate が反映されるタイミングを調整したい
### 利用シーン
- vuex-persistedstate を組み込んでみたが、Store に反映させるタイミングが遅いとき

使ってみるとわかるのですが、localStorage に保存した state を使って表示させている部分が切り替わらないことがあります。
いろいろな記事はあるのですが、私の利用環境にあった方法はみつからなかったので、以下のように対応しました。

```js:store.js
const state = {
  sampleArr: [],
};

const mutations = {
  save (state) {
    const data = JSON.parse(localStorage.getItem('test_store'));
    data.store.sampleArr = state.sampleArr;
    localStorage.setItem('test_store', JSON.stringify(data));
  },
  setSampleArr (state, arr) {
    state.sampleArr　= arr;
    mutations.save(state); // mutations の関数を実行したタイミングで setItem() メソッドを使って値を更新
  },
};

export default {
  namespaced: true,
  state,
  mutations,
};
```
上記は Vuex ストア内のモジュールのサンプルですが、コミット（mutations）のタイミングで localStorage の情報を更新するようにしました。
これで sampleArr を表示させている部分も setSampleArr 実行後に切り替わります。（個人的には解決できたときはガッツポーズでした）

## 4. カルーセルを JS ライブラリを使って実装したい
### 利用シーン
- vue 3 でカルーセルをライブラリを使って実装したいとき

Vue 3 に対応しているライブラリは、私が知っている範囲では以下の 3 つです。
- [Swiper](https://swiperjs.com/vue)
- [Keen-Slider](https://keen-slider.io/docs#usage-in-vue-3)
- [Splide](https://splidejs.com/integration/vue-splide/)

Keen-Slider と Splide はまだ使ったことがないのですが、機会があれば使ってみたいと思うライブラリです。
Keen-Slider の存在は [ics.media の記事](https://ics.media/entry/210902/)で知りました。

Slick.js は非公式で [vue-slick](https://github.com/staskjs/vue-slick)、[vue-slick-carousel](https://github.com/gs-shop/vue-slick-carousel) が存在していましたが、どちらも Vue 3 には対応していないようで機能しませんでした。

## 5. Vuex を初期化したい
### 利用シーン
- Vuex の state に保管した情報を初期化したいとき

これもいろんな書き方があると思うので一例ですが、Object.assign を利用してオブジェクトを上書きすることで初期値に戻しています。
以下も Vuex ストア内のモジュールの 1 ファイルという想定で書いています。

```js:store.js
const defaultState = {
  sampleData: {},
};

const state = defaultState;

const mutations = {
  reset (state) {
    Object.assign(state, getDefaultState);
  },
};

const actions = {
  resetStore ({ commit }) {
    commit('reset');
  },
};

export default {
  namespaced: true,
  state,
  mutations,
  actions,
};
```

## 最後に
ある程度慣れてくると気にもならなくなることが多いと思うので、JS フレームワークの実装に慣れてらっしゃる方が読むと「ふーん」くらいの内容かも知れませんが、よりよい対応などございましたらアドバイスなどいただけると嬉しいです。