LoginSignup
16
13

More than 5 years have passed since last update.

Vue.jsのナビゲーションガードを使って、ユーザ別のトップページに画面遷移させる。

Last updated at Posted at 2019-02-23

最近流行りのVue.jsを使ってWeb開発をしているのですが、その過程でVue.jsのナビゲーションガードを使って、ユーザ別のトップページに遷移させる、というのを実装しました。
イメージとしては、ヘッダーに共通の「Home」ボタンがあって、これを押下した際に、ユーザ別のトップページに遷移させるというのものです。

Vue.routerとは

Vue.jsの拡張ライブラリで、これを使うとシングルページアプリケーション(SPA)を構築することが出来ます。
シングルページアプリケーションは、複数のページ使ってを画面遷移をするのではなく、Webページ上の要素を置き換えることで画面遷移を実現する、というものです。

ナビゲーションガードとは

公式にも説明はありますが、簡単に説明します。ナビゲーションガードを使うと、画面遷移する際に処理を加えることができ、遷移先を変更したりすることが出来ます。

(その前に・・・)前提条件

今回はこのナビゲーション機能を使って、ヘッダーにあるホームボタンを押した際に、ユーザ別(一般ユーザ、管理者ユーザなど)のトップページに遷移させる処理を実装していきます。

が、その前に一つ前提条件があります。それはログインした際に、Vuexにログイン情報を保持しておくということです。
Vuexについての知識が浅い方はまず、それについて勉強してください。今回はログインの際に、「ログインID」、「パスワード」、「role」の3つの情報を、Vuexに保存しています。
なおこの「role」プロパティは1~3の値を取り、この値を見て、どのユーザー(一般ユーザーなのか管理ユーザーなのか)を判断していきます。

ユーザ別のトップページに遷移する

それでは実装していきましょう。まずはVue.routerの設定です。

main.js
 router.beforeEach((to, from, next) => {
//Vuexに保持しているloginオブジェクトを取得
  const currentUser = store.state.login
//遷移先が/loginのときは、Vuexの値を空にする
  if (currentUser.role) {
    if (to.path == '/login') {
      store.commit("loginUser", {})
    }
//roleプロパティによって遷移先を振り分け
    if (to.path == '/home') {
      if (currentUser.role == 1) {
        next({
          path: '/A01',
        })
      }else if(currentUser.role == 2){
        next({
          path: '/B01'
        })
      }else if(currentUser.role == 3){
        next({
          path: '/C01'
        })
      } else {
        next({
          path: '/login',
        })
      }    
    }    
  }
})

遷移先を空のページである、/homeに一旦指定しておき、実際の遷移先は、Vuexに保持しているloginオブジェクトを取り出し、そのroleプロパティの値によって、振り分けています。roleプロパティが存在しない際は、ログインページに遷移するようにしています。

また、空のページとして指定する/homeですが、index.jsに最低限pathを指定しないと動きません。(nameとcomponentは記述しなくてもよい。なので、importもしなくてよい。)

どういうことかというと、index.jsに以下の記述が最低限必要ということです。

index.js

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/login',
      name: 'Login',
      component: Login,
      meta: {
        isPublic: true  
      }
    },
    {
      path: '/A01',
      name: 'A01',
      component: A01
    },
    {
      path: '/B01',
      name: 'B01',
      component: B01
    },
    {
      path: '/C01',
      name: 'C01',
      component: C01
    },
//ここの記述が最低限必要。
    {
      path: '/home'
    },
    {
      path: '*', 
      redirect: '/Login'
    }
  ]
})

また、リダイレクト機能も実装しました。リダイレクトに関してはこちらを参考に実装しました。

main.js
 router.beforeEach((to, from, next) => {
  const currentUser = store.state.login

//省略

  if (to.matched.some(record => record.meta.isPublic)) {
    next()
  } else {
    if (currentUser.role) {
      next()
    } else {
      next({
        path: '/login',
        query: {
          redirect: to.path
        }
      })
    }
  }
})

全体としてはこんな感じです。

main.js
 router.beforeEach((to, from, next) => {
  const currentUser = store.state.login
  if (currentUser.role) {
    if (to.path == '/login') {
      store.commit("loginUser", {})
    }
    if (to.path == '/home') {
      if (currentUser.role == 1) {
        next({
          path: '/A01',
        })
      }else if(currentUser.role == 2){
        next({
          path: '/B01'
        })
      }else if(currentUser.role == 3){
        next({
          path: '/C01'
        })
      } else {
        next({
          path: '/login',
        })
      }    
    }    
  }

  if (to.matched.some(record => record.meta.isPublic)) {
    next()
  } else {
    if (currentUser.role) {
      next()
    } else {
      next({
        path: '/login',
        query: {
          redirect: to.path
        }
      })
    }
  }
})

これで、画面遷移する際の準備が出来ました。

続いて画面側の実装をします。既にお分かりの方もいるかもしれませんが、ヘッダーのホームボタンを押した際、遷移先に/homeを指定すれば、ユーザ毎のトップページに遷移先を振り分けてくれます。

Header.vue

<template>
  <div  class="container">

  <span v-if="this.$route.name !== 'A01' && this.$route.name !== 'B01' && this.$route.name !== 'C01' && this.$route.name !== 'Login'">
    <h3 @click="home" class="home"><font-awesome-icon icon="home" /></h3></span> 
      <span v-if="this.$route.name !== 'Login'">
        <h3 @click="logOut" class ="arrow"><font-awesome-icon icon="sign-out-alt" /></h3>
      </span>
    <div align="center" class="message">{{message}}</div>

  </div>
</template>

<script>
import Auth from '@/Auth'
import store from "@/store"

export default {
  name: 'Header',
  data () {
    return {
      message:'〇〇システム',
      Auth:Auth,
    }
  },

  methods: {
    home: function () {
          this.$router.push('/home')
         },
     user: function(){
       return this.$store.state.user
     },
    logOut: function () {
          this.$router.push('/login')
         }
    },

  computed:{
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>


.message{
  clear: both;
}


.home{
    float: left;
  cursor: pointer;
}

.user{
    float: right;
}


.arrow{
    float: right;
    cursor: pointer;
}


</style>

<template> の部分ででやっていることを少し捕捉すると、A01、B01、C01というように、各ユーザのトップページでは、「ホーム」ボタンを表示しないようにしています。また、ログインページにおいては、「ホーム」ボタンおよび「ログアウト」ボタンを表示しないようにしています。

もう一点。今回私のコードでは、ホームボタンにfont-awesomeのアイコンを使っていますが、これはなんでもかまいません。

<h3 @click="home" class="home"><font-awesome-icon icon="home" /></h3>

部分を

<h3 @click="home" class="home">Home</h3>

とすれば、アイコンではなくHomeという文字ボタンに変更できます。

はい。これでホームボタンを押した際、ユーザごとのトップページに遷移する、というのが実装できました。

(おまけ)存在しないURLをたたいた時に、ログイン画面に遷移する。

おまけです。存在しないURLをたたいたとき、ログイン画面に遷移するというのを実装します。
今回は先に完成形のコードをお見せします。

index.js

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/login',
      name: 'Login',
      component: Login,
      meta: {
        isPublic: true  
      }
    },
    {
      path: '/A01',
      name: 'A01',
      component: A01
    },
    {
      path: '/B01',
      name: 'B01',
      component: B01
    },
    {
      path: '/C01',
      name: 'C01',
      component: C01
    },
    {
      path: '*', 
      redirect: '/Login'
    }
  ]
})

この最後のところ

    {
      path: '*', 
      redirect: '/Login'
    }

で、存在しないURLをたたいたとき、/loginに遷移させる、というのを実現しています。

16
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
13