Vue Routerでルーティングごとに違うトランジションを設定する

Vue.jsでページごとに違うトランジションをつけたいと思った時に、どうやって実装するのがいいのかを調べたので、実装方法をまとめました。

やりたいこと

やりたかったことは、下記の感じです。

  1. 通常ページ遷移は画面の切り替え
  2. 一覧ページから個別ページへの遷移では、画面右からスライドイン
  3. 設定などのグローバルメニューが選択されたら下からスライドイン

要はネイティブアプリ的な動きにしたかった感じです。

解決策:CSSをスコープすればいい

答えは簡単で、下記のページにまとまってました。

【vue】vue-routerでviewごとに異なるcssトランジションを設定したい

引用させて頂くと、

つまり、描画されているコンポーネントのルートノードに対してCSSクラスが追加されるので、各コンポーネントごとにCSSトランジションを設定すれば各viewごとに異なるトランジションをさせることができます。

ただ単に設定しただけでは*-enter-active等のクラス名が重複してしまうので、各コンポーネントのスタイルをscoped cssにしてあげます。

トランジションに関しての説明もわかりやすい、良記事ですね。

stype scopedにすれば、そのviewなりcomponent限定のtransitionになるということですね。

実装

Vue Routerで切り替えがされる前提です。

簡単に流れを追うと、

  1. メインのApp.vueに共通transitionを追加する(今回は’page-in’)
  2. トランジションCSSはグローバルには書かない
  3. 個別のページに、トランジションCSSをscopedで書く
  4. トランジション効果がいらない場合は何も書かない

という感じです。

router.js

router.jsは普通にルートを書けばOKです。

省略
.
.
.

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/settings',
      name: 'settings',
      component: Settings
    },
    {
      path: '/list',
      component: List,
      children: [
        {
          path: 'page',
          component: Page
        }
      ]
    },
.
.
.
省略

App.vue

メインのApp.vueにtransitionを書きます。

<template>
  <div id="app">
    <transition name="page-in">
      <router-view/>
    </transition>
  </div>
</template>
.
.
.
略

すべてのページで「page-in」のトランジションを設定します。

List.vue

一覧ページには、特別トランジションを設定しません。ただし、個別ページに移動した際に右から出てきてほしいので、トランジションを使ってネストされた個別ページ(/list/page)を呼び出します。

<template>
  <div class="page">
    <h1>List>h1>
    <router-link to="/list/page">page</router-link>
    <transition name="slide-right">
      <router-view></router-view>
    </transition>
  </div>
</template>

Page.vue

こちらには右からスライドするトランジションをcssで書いておきます。

<template id="">
  <div class="single">
    <h1>page</h1>
  </div>
</template>

<style>
.single{
  width: 100%;
  height: 100%;
  background-color: #DDD;
  position: absolute;
  top: 0;
  right: 0;
  /* animation:slide .5s both; */
}
.slide-right-enter-active {
  transition: all .3s ease;
}
.slide-right-leave-active {
  transition: all .8s ease;
}
.slide-right-enter{
  transform: translateX(100%);
}
.slide-right-leave-to{
  transform: translateX(99%);
}
</style>

これで、一覧->個別ページの動きの時に、画面右からスライドインしてくる画面になります。

Settings.vue

こちらは下から画面が出てくる設定にします。

ここのトランジションには「page-in」が適用されています。「page-in」クラスはすべてのページで使われているクラスなので、cssをscopedして、このSettings.vueが呼び出された時だけに適用されるようにします。

<template>
    <div class="single">
      <span>Settings</span><br>
    </div>
  </transition>
</template>

<style scoped>
.page-in-enter-active {
  transition: all .3s ease;
}
.page-in-leave-active {
  transition: all .8s ease;
}
.page-in-enter{
  transform: translateY(100%);
}
.page-in-leave-to{
  transform: translateY(100%);
}
</style>

これで設定画面は下から出てくるようになります。


CSSだけで書くと辛い画面設定のスライド設定も、Vue.jsとVue Routerを使えば簡単に実装できました。

Vue.js用のフレームワークを使えばこういった機能はデフォルト入っていることが多いので便利なのですが、フレームワークは使わない機能まで含まれているためどうしてもサイズが大きくなってしまうのが難点です。

ちょっとした機能は自分で書いたほうがVue.jsの理解も深まるし、自分には向いているなと思いました。