iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 8
1
Modern Web

三十天路邊賭場上線了!系列 第 8

DAY08 遊戲平台、串接頁面(Vue)

前言

今天來加強我們昨天的頁面,讓他更生動且可以對API操作。我已經建好簡陋API用來開發前端,之後會再統一結構發出來。

Vuex

首先是我們Store,直接初始化我們會用到的方法,其實主要就是USER DATA以及ERRORS,所以操作也圍繞著他們。
登入成功後,是會將登錄資料存在本地localstorage,就可以保持登入了。

import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    user: null,
    errors: []
  },
  mutations: {
    // 收到設置User data
    SET_USER_DATA (state, userData) {
      // 設置state
      state.user = userData
      // 並設置在localstorage達到自動登入
      localStorage.setItem('user', JSON.stringify(userData))
      // 設置在每一次axoios的header Authorization 為 Bearer XXXXTOKEN
      axios.defaults.headers.common['Authorization'] = `Bearer ${userData.token}`
    },
    CLEAR_USER_DATA (state) {
      // 清除本地端user資料防止loggedIn再讀取到
      localStorage.removeItem('user')
      // reload這個頁面 重置所有vue檔案
      location.reload()
    },
    SET_ERROR_DATA (state, error) {
      // 設置state
      state.errors.push({
        id: state.errors.length,
        content: error
      })
      setTimeout(() => {
        state.errors.reverse()
        state.errors.pop()
        state.errors.reverse()
      }, 2000)
    }
  },
  actions: {
    pushError ({ commit }, credentials) {
      commit('SET_ERROR_DATA', credentials)
    },
    // 組建呼叫此register credentials就是我們帶入的data
    register ({ commit }, credentials) {
      // 回傳axios此一回傳 可用then串起來
      return axios.post('//localhost:3000/register', credentials)
    },
    login ({ commit }, credentials) {
      // 回傳axios此一回傳 可用then串起來
      return axios.post('//localhost:3000/login', credentials).then(
        // 回來的資料就commit到mutations修改state
        ({ data }) => {
          commit('SET_USER_DATA', data)
        }
      )
    },
    updateUserInfo ({ commit, state }) {
      return axios.post('//localhost:3000/userInfo', state.user).then(
        ({ data }) => {
          commit('SET_USER_DATA', data)
        }
      )
    },
    // 登出方法
    logout ({ commit }) {
      commit('CLEAR_USER_DATA')
    }
  },
  // 創造一個Getter取值
  getters: {
    loggedIn: state => {
      // 判斷是否有user 確定是否為登入狀態
      return !!state.user
    },
    userInfo: state => {
      return state.user
    }
  }
})

ERROR BLOCK 錯誤訊息顯示

我把錯誤訊息提示直接放在APP.vue,並直接讀store內的errors並渲染。有搭配transition-group做到動畫。

APP.vue

...以上省略

<div class="errorBlock"
     v-if="true">
  <transition-group name="list"
                    tag="div">
    <span v-for="(error, index) in this.$store.state.errors"
          :key="index">
      {{error.content}}
    </span>
  </transition-group>
</div>

...以下省略

LOGIN

登入頁面主要就是登錄,判斷是否為空,並把錯誤訊息加入到vuex,並由errorBlock顯示。

export default {
  data () {
    return {
      email: '',
      password: ''
    }
  },
  methods: {
    login () {
      if (!this.email || !this.password) {
        this.$store.dispatch('pushError', '欄位不能為空')
      } else {
        this.$store.dispatch('login', {
          email: this.email,
          password: this.password
        })
          .then(() => {
            this.$router.push({ name: 'gamelist' })
          }, (err) => {
            this.$store.dispatch('pushError', err.response.data.error)
          })
          .catch(err => {
            this.$store.dispatch('pushError', err.response.data.error)
          })
      }
    }
  }
}

重整自動登入

那我們還期待在登錄的時候,只要本地有資料就將使用者資料塞入vuex,這樣即可達成自動登入,且如果有任何401錯誤,就登出把資料清除。


new Vue({
  router,
  store,
  created () {
    // 自動登錄 取出localstorage
    const userString = localStorage.getItem('user')
    // 如果有東西的話
    if (userString) {
      // 轉成json
      const userData = JSON.parse(userString)
      // 設置vuex store
      this.$store.commit('SET_USER_DATA', userData)
      // axios 如果有任何錯誤發生 (更改自己的localstorage導致dashboard等等其他出錯)
      // 401是未授權
      axios.interceptors.response.use(
        response => response,
        error => {
          // 401就登出
          if (error.response.status === 401) {
            this.$store.dispatch('logout')
          }
          return Promise.reject(error)
        }
      )
    }
  },
  render: h => h(App)
}).$mount('#app')

總結

不得不說今天發文非常的趕,光是寫API就花了一點時間,明天再將API整理並把前端整理好了!


上一篇
DAY07 遊戲平台、搭建頁面(Vue)
下一篇
DAY09 遊戲平台、站台API、會員系統
系列文
三十天路邊賭場上線了!30

尚未有邦友留言

立即登入留言