Vue.jsでWebサービス開発 ⑬利用規約、ナビゲーションガード、トランジション

目次

GitHub

今回の作業が終了した後のブランチはこちらです。

https://github.com/skliber/excursion-demo/tree/finishing

最後の調整

前回の記事でほとんど完成していますが、公開するにはまだ足りない部分があります。
順に作っていきます。

UI調整

利便性のため、テーマとアイデアのもとを常に画面の上部に表示しておきます。
さらにちょっとした調整として、画面遷移したときにトランジションを実行するようにします。

ログアウト時にVuexをクリア

ログアウトしたときにVuexのステートを全て削除します。
Vuexにはステートを全て削除する方法が用意されていませんので、自分で実装します。

利用規約他の追加

以下の3つを作成します。

  1. サービスの利用規約
  2. サービスのプライバシーポリシー
  3. サービスの使い方

ルーティング調整

現状だとFirebaseでのログインや匿名ログインをしなくても、URLを知っていればその画面に移動できてしまいます。
これを修正するにはVueRouterのナビゲーションガードを使います。

UI修正とトランジション

テーマとアイデアのもとを常に表示し、遷移時のトランジションを設定します。
src/App.vueを以下のように修正します。

  • template el-mainブロック抜粋

    <el-main id="main">
      <el-row :gutter="10" class="bottom-margin" type="flex" justify="center"
      v-if="this.$route.path !== '/terms' &&
      this.$route.path !== '/privacy' &&
      this.$route.path !== '/howto' &&
      this.$route.path !== '/archive'">
        <el-col :xs="24" :sm="24" :md="16" :lg="14" :xl="14">
          <el-card shadow="hover" class="bottom-margin" v-if="this.$store.getters.theme">
            {{ this.$store.getters.theme }}
          </el-card>
          <el-card shadow="hover" class="bottom-margin" v-if="this.$store.getters.some">
            {{ this.$store.getters.some }}
          </el-card>
        </el-col>
      </el-row>
      <transition>
        <router-view/>
      </transition>
    </el-main>
    

    v-if=”this.$route.path !== ‘/terms’ 他

    表示する必要のないページでは非表示にします。このコードは特に酷いと思われますが、とりあえず意図通りには動きます。

    transition

    テンプレートではrouter-viewを囲むだけで、動作の指定はstyleで行います。

  • style 追加部分抜粋

    .v-enter-active {
      transition: opacity 1s;
    }
    .v-enter {
      opacity: 0;
    }
    .bottom-margin {
      margin-bottom: 10px;
    }
    

    .v-enter-active

    1秒かけてアニメーションします。

    .v-enter

    表示されるときは透明から徐々にはっきりしてくる感じにします。

    .bottom-margin

    それぞれのカードとrouter-viewが近すぎるので下部のみスペースを空けて表示を調整します。

ログアウト時にVuexのステートを全てクリア

手順

  1. src/store.jsのミューテーションに以下を追記します。
  • mutations
    reset (state) {
      const s = {
        theme: '',
        some: '',
        associates: [],
        ideas: {},
        userData: {}
      }
      Object.keys(s).forEach(key => {
        state[key] = s[key]
      })
    }
    

    reset (state)

    全ての値が空のオブジェクトを作り、forEachで現在のステートに上書きすることで初期化してます。

  1. src/store.jsのアクションに以下を追記します。
  • action
    clearAllState ({ commit }) {
      commit('reset')
    }
    

    clearAllState

    実行用のアクションです。

  1. src/App.vueのscript部分を修正します。
  • script 一部抜粋
    doLogout () {
      firebase.auth().signOut()
      this.$store.dispatch('clearAllState')
    },
    

    this.$store.dispatch(‘clearAllState’)

    ログアウトしたら先ほど追加したアクションを呼んでステートを初期化します。

利用規約の作成

利用規約はサービスを利用するユーザーとの決め事です。
Webサイトの利用規約のテンプレートを改変すれば楽に作成できます。
自分のサービスに合わせて必要な部分を変更し、単一ファイルコンポーネントで実装します。

作成
src/components/Terms.vue
src/components/Terms.vue GitHub

プライバシーポリシーの作成

プライバシーポリシーはサービス運営で受け取ることになるユーザーの情報をどう扱うか明示するためのものです。
やはりWebサイトの利用規約にテンプレートがありますので、これを改変すれば楽に作成できます。
Google Analyticsを使用する予定があるのならここでその旨を記載しましょう。

作成
src/components/Privacy.vue
src/components/Privacy.vue GitHub

使い方

今回はgifで使っている場面を録画してそのまま貼り付けています。
gifの作成にはScreenToGifを使用しました。

作成
src/components/Howto.vue
src/components/Howto.vue GitHub

ルーティングとフッターリンクの追加

作成した3つのページへのリンクをフッターに表示します。

手順

  1. src/App.vue</social-sharing>直下に以下を追記します。
  • template 一部抜粋
    <div id="footer-links" class="top-margin-middle bottom-margin">
      <el-row :gutter="10" type="flex" justify="center">
        <el-col :span="5">
          <span id="howto" @click="howto">使い方</span>
        </el-col>
        <el-col :span="5">
          <span id="terms" @click="terms">利用規約</span>
        </el-col>
        <el-col :span="5">
          <span id="privacy" @click="privacy">プライバシーポリシー</span>
        </el-col>
        <el-col :span="5">
          <span id="copylight"><a href="#">© 2018</a></span>
        </el-col>
      </el-row>
    </div>
    
  1. src/App.vuemethods内に以下を追記します。
  • script 一部抜粋
    terms () {
      this.$router.replace('/terms')
    },
    privacy () {
      this.$router.replace('/privacy')
    },
    howto () {
      this.$router.replace('/howto')
    }
    
  1. src/App.vuestyle内に以下を追記します。
  • style 一部抜粋
    #copylight a, #footer-links a, #terms, #privacy, #howto {
      text-decoration: none;
      cursor: pointer;
    }
    .top-margin-middle {
      margin-top: 20px;
    }
    

    cursor: pointer;

    そのままではカーソルが変化しないのでポインターにしています。

    .top-margin-middle

    シェアボタンと近すぎるので上部にマージンを設定します。

  1. src/components/Home.vueに注意書きを追加します。
  • template 一部抜粋

    <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
      <el-col :span="24">
        <el-button @click="doGoogleLogin" class="social-login btn-google"><font-awesome-icon :icon="['fab', 'google-plus']" /><span class="word">Googleアカウントでログイン</span></el-button>
      </el-col>
      <el-col :span="24">
        <el-button class="btn-anonymous" type="primary" @click="doLoginAnonymous" plain>ログインしないで使ってみる</el-button>
      </el-col>
      <el-col :span="24" class="top-margin-middle">
        <i class="el-icon-warning warning-icon"></i>本サービスを利用された場合は<span @click="moveTerms" class="warning-span">利用規約</span><span @click="movePrivacy" class="warning-span">プライバシーポリシー</span>にご同意を頂いたものとします。必ずご確認をお願いいたします。
      </el-col>
    </el-col>
    

    el-col :span=”24” class=”top-margin-middle”

    このel-colが追記する部分で、注意書きと利用規約とプライバシーポリシーへリンクを貼っています。

  • script 一部抜粋

    moveTerms () {
      this.$router.push('terms')
    },
    movePrivacy () {
      this.$router.push('privacy')
    }
    

    moveTerms & movePrivacy

    利用規約とプライバシーポリシーへ遷移するためのメソッドです。

  • style 一部抜粋

    .top-margin-middle{
      margin-top: 20px;
    }
    .warning-icon {
      color: #E6A23C;
    }
    .warning-span {
      color: #409EFF;
      cursor: pointer;
    }
    

    .top-margin-middle

    ログインボタンと近すぎるのでマージンを設定します。

    .warning-icon

    注意書きの左に配置したアイコンを黄色くしておきます。

    .top-margin-middle

    リンクであることがわかるように色とカーソルを変化させます。

  1. src/router/index.jsにルーティングを追加します。
    いつもと同じです。以下から実装済みのコードを確認してください。
    src/router/index.js GitHub

ナビゲーションガードの設定

ログインしていなければ遷移できないパスを設定します。
これはsrc/router/index.jsでそれぞれのオブジェクトにbeforeEnterを追記することで可能です。

{
  path: '/theme',
  name: 'Theme',
  component: Theme,
  beforeEnter (to, from, next) {
    if (store.getters.userData.uid) {
      next()
    } else {
      next('/')
    }
  }
}

beforeEnter (to, from, next)

遷移する前に呼ばれます。もしストアにuserData.uidが存在すればログインしているものとし、引数なしのnext()で目的のパスに遷移します。ストアにuserData.uidが存在しなければルートへ遷移します。

beforeEnterの追加が必要なパスは以下の通りです。

  • /theme
  • /some
  • /associate
  • /idea
  • /result
  • /archive

また、VueRouterでstoreにアクセスするにはimportが必要なので忘れずに追記しておきます。

import store from '@/store.js'

以下から実装済みのコードを確認してください。
src/router/index.js GitHub

動作確認

お疲れ様でした。これで全ての実装が終了しました。
$ npm run devを実行してhttp://localhost:8080/を開いて一通り使ってみましょう。
おかしな部分がなければOKです。

参考

Clear all stores or set them all to its initial state #1118
良いウェブサービスを支える「利用規約」の作り方 - Amazon
ナビゲーションガード - Vue Router