前言:
最近掉进了nuxt.js + ts 项目开发这个坑,今日心态炸裂,吐血整理。
1.nuxt项目中的持久化
1.1 Nuxt 有一个 cookie-universal-nuxt 模块来供服务端操作Cookie值 。
npm install cookie-universal-nuxt 使用方法: 提取:data.userInfo = app.$cookies.get('userInfo') 设置:this.$cookies.set("userInfo",this.formData.mobile,{maxAge:60*60*24*3}) //保存3天
1.2 修改根目录下的 nuxt.config.js,在modules中添加
modules: [ '@nuxtjs/axios', 'cookie-universal-nuxt', // ++++ ],
1.3.在store目录下的index,js里面有个 nuxtServerInit 方法
// 定义行为 const actions = { // 服务端调用 nuxtServerInit ({ commit }, { app }) { const data = {} data.userInfo = app.$cookies.get(Key.userInfoKey) data.accessToken = app.$cookies.get(Key.accessTokenKey) data.refreshToken = app.$cookies.get(Key.refreshTokenKey) data.redirectURL = app.$cookies.get(Key.redirectURLKey) commit('UPDATE_ALL_STATE', data) }, // .... m
1.4.页面使用
1. 测试, 2. 在 components/layout/Header.vue 中使用 3. this.$store.state.userInfo 可以获取到数据
1.5. 如果报错:Cannot read property 'get' of undefined
解决:查看 mengxuegu-blog-web\nuxt.config.js 文件中后面是否还有 modules: [ ]
2.请求拦截器的封装
大体分为两步,在plaugins里面建一个.js或者.ts文件,然后在nuxt.config.js中注册,最后重启项目
附上自己封装的拦截器,分为.js版本和ts版本,以供参考:
export default({store, route, redirect, $axios}) => { $axios.onRequest(config => { alert(config) // console.log("请求拦截器") const accessToken = store.state.accessToken if(accessToken) { // Authorization: Bearer token config.headers.Authorization = 'Bearer ' + accessToken } // 请求头添加token return config }) $axios.onResponse(response => { // console.log('响应拦截器:', response) // if(!store.state.accessToken) { // sendRefreshRequest(route, store, redirect) // } return response }) $axios.onError(error => { // console.log('响应异常:', error.response.status) if(error.response.status != 401 ) { return Promise.reject(error) } // 401 发送刷新获取新令牌 sendRefreshRequest(route, store, redirect) return Promise.reject('令牌过期,重新登录') }) } let isLock = true // 防止并发重复发送刷新令牌请求, true 还未发送,false正在请求刷新 const sendRefreshRequest = (route, store, redirect) => { if(isLock && store.state.refreshToken) { isLock = false // 发送请求到认证客户端,通过刷新令牌获取新令牌 redirect(`${process.env.authURL}/refresh?redirectURL=${redirectURL(route)}`) }else { isLock = true // 没有刷新令牌,跳转到登录页 // 重置用户状态 // console.log('跳转到登录页') store.commit('RESET_USER_STATE') // 跳转到登录页 redirect(`${process.env.authURL}?redirectURL=${redirectURL(route)}`) } } // 获取重定向地址 const redirectURL = (route) => { // 客户端 if(process.client) { return window.location.href } // 服务端 process.env._AXIOS_BASE_URL_ http://localhost:3000/api http://blog.mengxuegu.com/api return process.env._AXIOS_BASE_URL_.replace('api', '') + route.path }
import axios, { AxiosInstance, AxiosResponse, AxiosRequestConfig, AxiosError } from 'axios' const throwErr = (code: number, response: AxiosResponse) => { let message: string = '请求错误' switch (code) { case 400: message = '请求错误' break case 401: message = '未授权,请登录' break case 403: message = '拒绝访问' break case 404: message = `请求地址出错: ${response.config.url}` break case 408: message = '请求超时' break case 500: message = '服务器内部错误' break case 501: message = '服务未实现' break case 502: message = '网关错误' break case 503: message = '服务不可用' break case 504: message = '网关超时' break case 505: message = 'HTTP版本不受支持' break default: } return message } const requestInterceptors = { config: (config: AxiosRequestConfig) => { // config.headers = { // 'Authorization': 'Bearer' // } if (config.method && config.params) { for (const i in config.params) { if (config.params[i] == '' && config.params[i] !== 0 && config.params[i] !== false) { config.params[i] = null } } } return config }, error: (error: AxiosError) => { return Promise.reject(error) } } const responseInterceptors = { response: (response: AxiosResponse) => { const res = response.data return Promise.resolve(res) }, error: (error: AxiosError) => { if (error && error.response) { // const res = { // Data: null, // State: error.response.status, // Msg: throwErr(error.response.status, error.response) // } return Promise.reject(error.response) } } } class Request { protected axiosInstance: AxiosInstance; constructor(baseURL: string) { this.axiosInstance = axios.create({ baseURL, timeout:15000 }) this.axiosInstance.interceptors.request.use(requestInterceptors.config, requestInterceptors.error) this.axiosInstance.interceptors.response.use(responseInterceptors.response, responseInterceptors.error) } } export default Request