2020 年 11 月 18 日

IT Skills 波林

Polin WEI – 資訊工作者的技術手札

Vuex 的對於帳號登入的實際運用範例

2 min read

Vuex & vuex-persistedstate  的對於帳號登入的實際運用範例

 

什麼情況下應該使用 Vuex

Vuex 可以做為網站的全域狀態管理,可以將全域狀態集中管理。如果您不打算開發大型單頁應用,使用 Vuex 可能是繁瑣冗餘的。如果您的應用夠簡單,您最好不要使用 Vuex。一個簡單的 store 模式就足夠您所需了。但是,如果您需要構建一個中大型單頁應用,您很可能會考慮如何更好地在元件外部管理狀態,Vuex 將會成為自然而然的選擇。

 

在專案結構下通常會有多個組件,組件內可能又有組件,組件的溝通,通常會用到 emit 和 propsemit 回來, props 下去,所以組件之間的溝通,就會有超多 emit跟 props ,為了處理大型專案像是這樣跨結構的兄弟組件溝通,而非單純父子組件溝通,Vuex 就產生了。

 

Vuex 裡面,儲存狀態的為 State,組件需要更動狀態時,需要透過 Actions 發出一個 Commit 去呼叫 Mutations,再由 Mutations 去更改 State。整個 Vuex 的方法也稱為 store

 

vuex

基本的教學,可以觀看官網,接下來用帳號登入來一一說明整個步驟流程。

 

Vue2

npm install vuex --save

Vue3

# If using Vue 3.0 + Vuex 4.0:
npm install [email protected] --save

 

安裝好之後,在 /src 資料夾中新增一個 store.js 檔案,新增好之後先來建立一個 State 跟 Mutations:

import Vue from 'vue'
import Vuex from 'vuex'
import router from '@/router'
Vue.use(Vuex)

const user = JSON.parse(sessionStorage.getItem('user'));
const initialState = user
  ? { status: { loggedIn: true },  user: user }
  : { status: { loggedIn: false }, user: null };



export default new Vuex.Store({
  state: initialState ,
  mutations: {
    loginSuccess(state, user){
      state.status = { loggedIn: true };
      state.user = JSON.parse(user);
    },
    logout() {      
      sessionStorage.clear();
      router.push("/Login")
    },
  },
  actions: {
    login(context, user) {
      context.commit('loginSuccess', user)      
    },
    logoutAction({commit}) {      
      commit('logout')      
    }
  }
})

 

  • 匯入(Import)

接下來在 main.js 裡面把 store 拉進來:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import i18n from './i18n'
import VueAxios from 'vue-axios'
import axios from './plugins/axios.js'

Vue.use(VueAxios, axios)  // 這讓你可以使用 this.axios or this.$http...
Vue.use(require('vue-moment'))
Vue.config.productionTip = false

new Vue({  
  router,
  store,
  i18n,  
  render: h => h(App)
}).$mount('#app')

i18n.locale = navigator.language;

 

  • 寫入 store ( Usage in component )

Login.vue 頁面:在帳號登入後,寫入 store

<script>
import {apiUserLogin} from '@/apis/SystemApi.js';
export default {
  methods: {    
    async Login() {      
      if (this.username && this.password) {
        let data = {"username" : this.username, "password": this.password};
        let res =  await apiUserLogin(data).then(data=>data);
        let user = res.user;
        if (user){
          sessionStorage.setItem("user", JSON.stringify(user));          
          this.$store.commit('loginRequest',user)
        }
      }
    },
  },
};
</script>

 

  • 在選單中,依store的資料來判斷要呈現那些選單

使用 mapState 運用在 computed 中,就如同 data() 中定義的值,可以使用 this. 來呼叫了。

<template>
 <Listbox v-model="selectedUserItem" :options="userItems" optionLabel="name" @change="userItemSelected" style="width:15rem">
  <template #option="slotProps">
   <i :class="slotProps.option.icon"> </i>
   <span> {{slotProps.option.name}} </span>
  </template>             
 </Listbox>
</template>

<script>
import { mapState } from 'vuex'
export default {
 data() {
  return {
   selectedUserItem : null,             
  }
 },
 methods: {
  userItemSelected(event){
   const actionCode = event.value.code;
   let user = sessionStorage.getItem("user");   
   switch (actionCode) {
    case 'Login':
      this.$router.push(event.value.to);
     break;
    case 'Logout':
      if (user) {
        sessionStorage.removeItem("user")                                   
      }
      this.$router.push("/Login");
     break;
    default:
     break;
   }                
  }
 },
 computed: {
  ...mapState({
    status: (state) => state.status,
    user : state => state.user
  }),
  userItems() {             
   return this.status.loggedIn ?
    [ 
     {name: 'Log Out', code: 'Logout', icon: 'pi pi-fw pi-sign-out' },
     {name: 'Settings', code: 'Settings', icon: 'pi pi-fw pi-cog' },
     {name: this.user.username, code: 'Profile', icon: 'pi pi-fw pi-user' }]
    :
    [ {name: 'Log In', code: 'Login', icon: 'pi pi-fw pi-sign-in', to: '/Login' },
     {name: 'Settings', code: 'Settings', icon: 'pi pi-fw pi-cog' }]
  }
 }


}
</script>

 

  • Store 資料初始後與保留

因為 Vuex 只是在對當前頁面的資料保持一致性,當頁面刷新 ( pgae refresh ) 時,state 就會被清空,為了避免這情形,可以使用 vuex-persistedstate 來將資保存在用戶端的 localStorage(預設) 或 sessionStorage 裡。可以將 store 修改如下:

import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from "vuex-persistedstate";
import router from '@/router'
Vue.use(Vuex)

const initUserStore = () => {
  return {
    status: { loggedIn: false },
    user: null
  }
}

export default new Vuex.Store({
  plugins: [createPersistedState({
    storage: sessionStorage,
  })],
  state: initUserStore(),
  mutations: {
    loginSuccess(state, user){
      state.status = { loggedIn: true };
      state.user = JSON.parse(user);
    },
    logout() {      
      sessionStorage.clear();
      router.push("/Login")
    },
    resetState(state) {      
      Object.assign(state, initUserStore());      
    }
  },
  actions: {
    loginAction(context, user) {
      context.commit('loginSuccess', user)      
    },
    logoutAction({commit}) {      
      commit('logout')
      commit('resetState')
    }
  }
})

 

 

參考: [Vue] Vuex 是什麼? 怎麼用? — State、Mutations

Copyright © All rights reserved. | Newsphere by AF themes.