美文网首页
Vue SSR 项目 Nuxt.js 框架之《vuex如何实现状

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

作者: 酷酷的凯先生 | 来源:发表于2022-03-10 19:34 被阅读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;
        })
    }
    

    相关文章

      网友评论

          本文标题:Vue SSR 项目 Nuxt.js 框架之《vuex如何实现状

          本文链接:https://www.haomeiwen.com/subject/ujofdrtx.html