[Nuxt.js]動的にページ遷移のtranstionを変更する

# 目的
今回したいことは、ユーザーのアクションによってページ遷移のアニメーションを変えることです。
「nuxt transition page 動的」などと検索をかけた結果、記事が出てこなかったので記録しておきます。

# 結論までの道すじ
まず、ページ遷移の際は`transition`プロパティを用います。（[Nuxt.jsドキュメント](https://ja.nuxtjs.org/docs/2.x/components-glossary/pages-transition/)）そのため、一度ドキュメントを見て、自分のしたいことが実現可能かを調査します。

```Nuxt.js
export default {
  // Can be a String
  transition: ''
  // Or an Object
  transition: {}
  // or a Function
  transition (to, from) {}
}
```
ドキュメントによると、`transition`プロパティでは、stateやstoreへのアクセスができず、値やアクションによるtransition名の変更はできないようになっています。試しに、

```Nuxt.js
data: () => {
  return {
    transitionName: 'slide-left'
  }
},
transition: this.transitionName
```
などと書くと、thisが参照できない旨のエラーが出てしまい、期待する動作ができません。
以上より、transition名を動的に変えることはできないと考えます。

* * *

次に、クラス名に着目します。transitionでのアニメーションの仕組みは、遷移時にクラス名が動的に当てられ、そのクラス名で指定したCSSによってアニメーションが行われます。このあたりは、[Vue.jsのドキュメント](https://jp.vuejs.org/v2/guide/transitions.html)が参考になります。
たとえば、スライドしながらページ遷移させたいと思ったら、以下のように実装します。

```css
/* 左右にスライドするページ遷移アニメーション */
.slide-enter-active,
.slide-leave-active {
  transition: transform 0.5s ease;
}
.slide-leave-to {
  transform: translateX(100vw);
}
.slide-enter {
  transform: translateX(-100vw);
}
```
では、このクラス名が当てられる要素、もしくはそれより上の階層の要素に対して、何らかのクラス名を当てて、子孫セレクタに、アニメーションのCSSを書いても期待した動きができるのでしょうか。今回は右にスライドさせたいという意味を込めて、`right`というクラス名を親要素につけている想定で進みます。

```css
/* 右にスライドするページ遷移アニメーション */
.right .slide-enter-active,
.right .slide-leave-active {
  transition: transform 0.5s ease;
}
.right .slide-leave-to {
  transform: translateX(100vw);
}
.right .slide-enter {
  transform: translateX(-100vw);
}
```

当然ですが、問題なく動作します。そこで、左へスライドするためのCSSも準備します。

```css
/* 左右にスライドするページ遷移アニメーション */
.right .slide-enter-active,
.right .slide-leave-active {
  transition: transform 0.5s ease;
}
.right .slide-leave-to {
  transform: translateX(100vw);
}
.right .slide-enter {
  transform: translateX(-100vw);
}
.left .slide-enter-active,
.left .slide-leave-active {
  transition: transform 0.5s ease;
}
.left .slide-leave-to {
  transform: translateX(-100vw);
}
.left .slide-enter {
  transform: translateX(100vw);
}
```
どこかの要素に、`.left`、`.right`をつけてみてください。`.left`の時は左にスライド、`.right`の時は右にスライドするはずです。
あとは、クラス名を動的に付与すれば、完成です。

クラス名の動的な付与の方法は、様々あると思いますが、僕が実装したものを最後にご紹介したいと思います。
この実装の意図としては、できるだけ、stateやstoreを汚さないように、また、アクションを実行するメソッド内だけを見て、何をしたいかがわかるないようにすることです。

```Nuxt.js
methods: {
  /**
   * 画面遷移時にスワイプした方向にアニメーションさせる
   * @param {String} direction スワイプ方向
   */
  swipe(direction) {
    // 左にスワイプした場合
    if (direction === 'left') {
      const container = document.querySelector('.wrapper-container')
      if (container.classList.contains('right')) {
        container.classList.remove('right')
      }
      container.classList.add('left')
    // 右にスワイプした場合
    } else if (direction === 'right') {
      const container = document.querySelector('.wrapper-container')
      if (container.classList.contains('left')) {
        container.classList.remove('left')
      }
      container.classList.add('right')
    }
    // 画面遷移
    this.$router.push('/')
  }
}
```

# 最後に
わからないことを検索して、調べて出てこなかった時、「うわーできないー」と投げ出したくなるメンタルを持ち合わせているのですが、順序立てて考えていくと、意外と解決方法は簡単であったりします。エンジニアとしてひよこなので、とりあえずググって該当の記事を見つける、という癖がついてしまっていますが、何故できないのか、何をしたいのかを常に考えて調査すれば無駄な時間が削られると思いました。