Vue<vuex在項目中的使用>

此篇文章是介紹利用 vuex 儲存用戶登錄時的相關(guān)信息的使用方法。

聲明:前面部分是剛開始對vuex的接觸,后面部分是學(xué)習(xí)后對vuex使用的部分優(yōu)化,想直接用最新的,可以直接找到 20200819 部分。

效果圖:
image.png
使用方法:

相關(guān)配置文件


image.png

index.js

import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
Vue.use(Vuex)
export default new Vuex.Store({
    //模塊引入
    modules:{
        user:user
    }
})

user.js


export const USER_SIGNIN = 'USER_SIGNIN' //登錄成功
export const USER_SIGNOUT = 'USER_SIGNOUT' //退出登錄
export const USER_INFO_COMMIT = 'USER_INFO_COMMIT' //配合sessionStorage解決vux刷新丟失問題
export default {
    // 存儲狀態(tài)(變量)
    state: {
        userInfo: {},//儲存用戶相關(guān)信息
        userLogin: false,//用戶登錄狀態(tài)
    },
    // 對數(shù)據(jù)獲取之前的再次編譯,可以理解為state的計算屬性 this.$store.getters.方法名。
    getters: {
      
    },
    // 修改狀態(tài),并且是同步的。在組件中使用$store.commit('',params)
    mutations: {
        //用戶登陸方法
        [USER_SIGNIN](state, user) {
            //儲存用戶相關(guān)信息
            sessionStorage.setItem('userInfo', JSON.stringify(user))
            sessionStorage.setItem('userLogin', 'true')
            if (JSON.stringify(user)) {
                //解決用戶信息未及時更新問題
                Object.assign(state.userInfo, sessionStorage.getItem('userInfo') ? JSON.parse(sessionStorage.getItem('userInfo')) : user)
                //更新用戶登錄狀態(tài)
                state.userLogin = sessionStorage.getItem('userLogin') ? JSON.parse(sessionStorage.getItem('userLogin')) : false
            }
        },
        //用戶退出登錄方法
        [USER_SIGNOUT](state) {
            state.userLogin = false;
            state.userInfo = {};
            //清除sessionStorage內(nèi)的所有記錄
            sessionStorage.clear();
        },
        //解決瀏覽器刷新頁面數(shù)據(jù)丟失問題(根據(jù)之前儲存的sessionStorage相關(guān)信息來判斷)
        [USER_INFO_COMMIT](state) {
            Object.assign(state.userInfo, sessionStorage.getItem('userInfo') ? JSON.parse(sessionStorage.getItem('userInfo')) : {})
            state.userLogin = sessionStorage.getItem('userLogin') ? JSON.parse(sessionStorage.getItem('userLogin')) : false;
        },
    },
    // 異步操作
    actions: {
        [USER_SIGNIN]({ commit }, user) {
            commit(USER_SIGNIN, user)
        },
        [USER_SIGNOUT]({ commit }) {
            commit(USER_SIGNOUT)
        },
        [USER_INFO_COMMIT]({ commit }) {
            commit(USER_INFO_COMMIT)
        }
    }
}

main.js

import store from './store/index' //引入

/* eslint-disable no-new */
new Vue({
  el: '#app',
  store, //引入
  router,
  components: { App },
  template: '<App/>'
})

配置完成后,就可以直接在vue組件中使用

xxx.vue組件

<template>
  <div style="margin:200px 0">
    <p>登錄狀態(tài):{{userLogin}}</p>
    <p>用戶信息:{{userInfo}}</p>
    <button @click="loginIn()">登錄</button>
    <button @click="loginOut()">退出</button>
  </div>
</template>

<script>
export default {
  computed: {
    userLogin() {
      if (this.$store.state.user.userLogin) {
         return this.$store.state.user.userLogin;
      } else {
        this.$store.commit("USER_INFO_COMMIT");
        return this.$store.state.user.userLogin;
      }
    },
    userInfo() {
      if (this.$store.state.user.userLogin) {
        return this.$store.state.user.userInfo;
      } else {
        this.$store.commit("USER_INFO_COMMIT");
        return this.$store.state.user.userInfo;
      }
    }
  },
  data() {
    return {
      userMsg: {
        name: "小明",
        age: "18",
        sex: "男"
      }
    };
  },
  methods: {
    loginIn() {
      this.$store.commit("USER_SIGNIN", this.userMsg);
    },
    loginOut() {
      this.$store.commit("USER_SIGNOUT");
    }
  }
};
</script>

<style>
</style>

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

20200819代碼優(yōu)化調(diào)整:

程序員都是在不斷成長的,下面的代碼是針對之前使用vuex的部分優(yōu)化。


image.png

模塊引入
相比之前的模塊引入,這邊也是同樣按照 modules 目錄下,進(jìn)行的配置。不過是直接通過遍歷文件目錄實現(xiàn)的,不需要再一個個去寫了。

index.js

import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'

Vue.use(Vuex)
// 把modules文件下的 js文件返回出來
// https://webpack.js.org/guides/dependency-management/#requirecontext
const modulesFiles = require.context('./modules', true, /\.js$/)

// you do not need `import app from './modules/app'`
// it will auto require all vuex module from modules file
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  // set './app.js' => 'app'
  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
  const value = modulesFiles(modulePath)
  modules[moduleName] = value.default
  return modules
}, {})

const store = new Vuex.Store({
  modules,
  getters
})

export default store

getters.js
getters.js里面是所有你想對外報漏的數(shù)據(jù)

const getters = {
    name: state => state.user.name,
    phoneNo: state => state.user.phoneNo,
}
export default getters

user.js
login, logout, getInfo 相當(dāng)于針對用戶的一些api接口;(可以忽視掉)

state 里面儲存的為用戶token,name和phoneNo,其中在getters.js里面,可以實現(xiàn)了針對 user 模塊內(nèi) name和phoneNo 數(shù)值的對外暴露

mutations 里面實現(xiàn)了重置用戶信息,儲存用戶token,儲存name,儲存phoneNo的修改方法;

actions 里面是針對用戶登錄,獲取用戶信息,以及用戶退出登陸的異步方法。此處你會看到有使用 Promise 異步操作,主要用于使用過程中的 await數(shù)據(jù)等待處理。 不太理解async/await 的可 參考此篇文章。

namespaced: true,主要是為了解決不同模塊命名沖突的問題,將不同模塊的namespaced:true,之后在不同頁面中引入getter、actions、mutations時,需要加上所屬的模塊名。

類似這樣,就可以在使用頁面內(nèi),直接對vuex內(nèi),user模塊內(nèi)的login用戶登陸方法進(jìn)行調(diào)用。
this.$store.dispatch("user/login");


import { login, logout, getInfo } from '@/api/user'
import { getToken, setToken, removeToken } from '@/utils/auth'

const getDefaultState = () => {
    return {
        token: getToken(),
        name: "",
        phoneNo: "",
    }
}

const state = getDefaultState()

const mutations = {
    RESET_STATE: (state) => {
        Object.assign(state, getDefaultState())
    },
    SET_TOKEN: (state, token) => {
        state.token = token
    },
    SET_NAME: (state, name) => {
        state.name = name
    },
    SET_PHONENO: (state, phoneNo) => {
        state.phoneNo = phoneNo
    },
}

const actions = {
    // 用戶登錄,獲取token,并儲存到cookie里面
    login({ commit }, userInfo) {
        return new Promise((resolve, reject) => {
            commit('SET_PHONENO', '15518270529')
            resolve()
            // //調(diào)用登錄接口
            // login().then(response => {
            //     const { data } = response
            //     // 儲存到cookie里面
            //     commit('SET_TOKEN', data.token)
            //     setToken(data.token)
            //     resolve()
            // }).catch(error => {
            //     reject(error)
            // })
        })
    },
    //調(diào)用獲取用戶信息的接口
    getInfo({ commit, state }) {
        return new Promise((resolve, reject) => {
            //調(diào)用獲取用戶信息接口
            getInfo().then(response => {
                const { data } = response
                if (!data) {
                    reject('Verification failed, please Login again.')
                }
                const { name, phoneNo } = data
                commit('SET_PHONENO', phoneNo)
                commit('SET_NAME', name)
                resolve(data)
            }).catch(error => {
                reject(error)
            })
        })
    },
    //用戶退出登錄
    logout({ commit, state }) {
        return new Promise((resolve, reject) => {
            logout(state.token).then(() => {
                removeToken() // must remove  token  first
                commit('RESET_STATE')
                resolve()
            }).catch(error => {
                reject(error)
            })
        })
    },
}

export default {
    namespaced: true,
    state,
    mutations,
    actions
}

xxx.vue組件

import { mapGetters } from "vuex";
//計算屬性
 computed:{
   //通過getter.js對外暴露的 phoneNo 值進(jìn)行使用
   // {{phoneNo}} 數(shù)值使用
    ...mapGetters(['phoneNo'])
  },
  methods: {
    async isLogin() {
    //使用 try/catch 抓取錯誤信息,如果登陸失敗則會輸出錯誤信息,不往下執(zhí)行
      try {
        await this.$store.dispatch("user/login");
        //如果登陸成功才會 輸出 ‘登陸成功’
        console.log('登陸成功')
      } catch (error) {
        console.log(error);
      }
    }
  }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容