Vue SSR 项目 Nuxt.js 框架之《vuex如何实现状

2022-03-10  本文已影响0人  酷酷的凯先生

# 前言

在项目开发中肯定会用到数据存储,而数据存储一般会选择Vuex。那么怎么在nuxt中实现Vuex的使用及持久化呢?
nuxt是以模块的方式加载store文件夹下所有的.js文件的,并将其转换为状态树。其中index.js是根模块,其余命名都是子模块。

# 创建根模块 index.js

store / index.js

// 定义 state
export const state = () => ({
    token: 'token'
});

// 定义 actions
export const mutations = {
    M_UPDATE_TOKEN(state, data) {
        state.token = data
    }
};

// 定义 actions
export const actions = {
    A_TOKEN_INFO({ commit, state }, data) {
        commit('M_UPDATE_TOKEN', '获得的token')
    }
};

// 定义 getters
export const getters= {
    getToken(state) {
        return state.token || '';
    }
}

# 创建子模块 user.js

store / user.js

// 定义 state
export const state = () => ({
    uName: ''
});

// 定义 actions
export const mutations = {
    M_UPDATE_UNAME(state, data) {
        state.uName = data
    }
};

// 定义 actions
export const actions = {
    A_UPDATE_UNAME({ commit, state }, data) {
        commit('M_UPDATE_UNAME', '张三');
    }
};

// 定义 getters
export const getters= {
    getUName(state) {
        return uName.token || '';
    }
}

在控制台打印出我们的状态树可以看到子模块user已经加载到根模块上,如下:

image.png

其他操作和使用和普通Vue项目一样使用并无差别,比如:

某页面

export default{
    computed:{
        // 获取根模块下的 getters 返回的 token
        ...mapGetters(['getToken']),
        // 拿取子模块的 state 数据
        ...mapState('user', ['uName']),
        // 或者
        ...mapState({uName:state=>state.user.uName}),
    },
    mounted(){
        this.M_UPDATE_UNAME('张三');
        // 或者
        this.A_UPDATE_UNAME('张三');
    },
    methods:{
        ...mapMutations('user', ['M_UPDATE_UNAME']),
        ...mapActions('user', ['A_UPDATE_UNAME'])
    }
}

# 状态持久化与校验Token

nuxt中实现状态持久化需要借助cookie-universal-nuxt模块,整体思路就是:

  1. 在登录时将用户的token的同时存入Vuexcookie里。
  2. 页面刷新后会触发store文件夹下的根目录的index.js文件里的nuxtServerInit钩子函数,在这个函数里将cookie的信息重新注册到Vuex状态里。
  3. $axios的请求拦截器onRequest里每次请求时都从状态里取用户token,取不到则说明用户没有登录,即跳转至登录页,让用户登录。

第一步:安装 cookie-universal-nuxt

npm i cookie-universal-nuxt --save-dev

第二步:在 nuxt.config.js 中引入 cookie-universal-nuxt

export default {
    modules:['@nuxtjs/axios', 'cookie-universal-nuxt']
}

第三步:将用户token同时保存到 Vuex 和 cookie 中

// 模拟用户登录接口
this.$axios.post('/login', {uName: 'admin', pwd: '123456'}).then(res => {
    // 将用户信息同步到 Vuex 和 cookie
    this.$cookies .set('user_token', res.token);
    this.$store.commit('M_UPDATE_TOKEN', res.token);
})

第四步:页面强刷时将cookie中的信息取出赋值给 Vuex

store / index.js

// 定义actions
export const actions  = {
    nuxtServerInit(store, { app: { $cookies } }){
        let token = $cookies.get('user_token') ? $cookies.get('user_token') : '' ;
        store.commit('M_UPDATE_TOKEN', token );
    }
}

这时登录拿到token后同步到Vuexcookie,强刷页面后会从cookie里取出信息在赋值回Vuex里,所以保证了Vuex里的数据也不会丢失。

第五步:请求拦截器里校验 token

export default function({ $axios, redirect, router, store }) {
    // 请求拦截器
    $axios.onRequest(config => {
        config.headers.token = store.state.token;
        return config;
    })

    // 响应拦截器
    $axios.onResponse(res => {
        const resDate = res.data;
        // 如果返回错误信息为 token 类似的,则跳转至登录页
        if (resDate.msg == 'token无效') {
            redirect('/login');
        }
        return resDate;
    })
}
上一篇下一篇

猜你喜欢

热点阅读