nuxt3.0学习-二、nuxt3.0的请求相关内容、状态管理(useState/Pinia)、cookie管理(useCookie)、token续期

请求相关内容

nuxt3.0提供的多种数据访问 API

上一次是nuxt3.0的安装和约定式的使用

接下来就是使用请求调整,Nuxt3 中提供的多种数据访问 API:

  1. $fetch;

    使用时机:

    首屏渲染,调用发生在服务端;

    客户端激活之后,调用发生在客户端。

  2. useAsyncData;

    该方法和 useFetch 相比功能上是相同的,但是更底层,使用方法类似于 ahooks 库中的 useRequest,我们需要提供一个用于缓存去重的 key 和数据请求的处理函数。也就是说,useFetch 相当于:useAsyncData(key, () => $fetch(url))。

  3. useLazyAsyncData;

    该方法等效于useFetch设置了lazy选项为 true,不同之处在于它不会阻塞路由导航,这意味着我们需要处理 data 为 null 的情况(或者通过 default 选项给 data 设置一个默认值)。

  4. useFetch;

    页面、组件或者插件中可以使用useFetch获取任意 URL 资源。useFetch是对useAsyncData和$fetch的封装,只需传入请求的 URL 或者一个请求函数即可,一些选项会自动填入,用起来最简洁,是最推荐的数据获取方式。

  5. useLazyFetch

    该方法等效于useFetch设置了lazy选项为 true,不同之处在于它不会阻塞路由导航,这意味着我们需要处理 data 为 null 的情况(或者通过 default 选项给 data 设置一个默认值)。

使用封装

$fetch、useFetch封装方法

// http请求封装 //
import { ElMessage } from 'element-plus'
export const fetchConfig = { baseURL: getBaseUrl(),//请求配置
    headers: { ContentType: 'multipart/form-data' }
}
//请求体封装
function useGetFetchOptions(options = {}){ options.baseURL = options.baseURL ?? fetchConfig.baseURL
    options.headers = options.headers ?? { ContentType: fetchConfig.headers.ContentType
    }
    options.initialCache = options.initialCache ?? false
    options.lazy = options.lazy ?? false
    options.showError = options.showError ?? true
    options.needReject = options.needReject ?? false
    // 用户登录,默认传token
    const Authorization = useCookie("cookies名称")
   
    // if(Authorization.value){ 
      options.headers.Authorizations = Authorization.value
    // }
    return options
}
//http请求封装
export async function useHttp(key,url,options = {}){ options = useGetFetchOptions(options)
    options.key = key
    if(options.$){ // 通过插件或中间件调用时
        return new Promise((resolve, reject) => { $fetch(url, options).then(res => { if (res.code == 200) { resolve(res);
            const toggleTokenBool = useState('tokenBool')
            toggleTokenBool.value = false
          } else if (res.code == 20001) { // token失效处理
            reject(res)
            const toggleTokenBool = useState('tokenBool')
            if(!toggleTokenBool.value){ toggleTokenBool.value = true
              const route = useRoute();
              const token = useCookie("websiteAuthorization");
              token.value = null;
              ElMessage({ message: '登录已失效,请重新登录!'});
              navigateTo("/login?from=" + route.fullPath);     
            } 
          } else { //若需要报错提醒
            if (process.client && options.showError && res.msg) { ElMessage({ message: res.msg, customClass: "message-zindex" });
            }
            if (options.needReject) { resolve(res);
            }else{ reject(res)
            }
          }
          }).catch((err) => { reject(err)
          })
        })
    }else{ //路由中调用时
      return new Promise((resolve, reject) => { useFetch(url, { ...options}).then(({ data, error }) => { if (error.value) { reject(error.value)
            return
          }
          const res = data.value
          if (error.value) { reject(error.value);
            return;
          }
          const res = data.value;
          if (res.code == 200) { resolve(res);  
            const toggleTokenBool = useState('tokenBool')
            toggleTokenBool.value = false                
          } else if (res.code == 20001) { // token失效处理
            reject(res)
            const toggleTokenBool = useState('tokenBool')
            if(!toggleTokenBool.value){ toggleTokenBool.value = true
              const route = useRoute();
              const token = useCookie("websiteAuthorization");
              token.value = null;
              ElMessage({ message: '登录已失效,请重新登录!'});
              navigateTo("/login?from=" + route.fullPath);     
            } 
          } else { //若需要报错提醒
            if (process.client && options.showError && res.msg) { ElMessage({ message: res.msg, customClass: "message-zindex" });
            }
            if (options.needReject) { resolve(res);
            }else{ reject(res)
            }
          }
        }).catch((err) => { reject(err)
        })
      })
    }
}
// GET请求
export function useHttpGet(key,url,options = {}){ options.method = "GET"
    return useHttp(key,url,options)
}
// POST请求
export function useHttpPost(key,url,options = {}){ options.method = "POST"
    return useHttp(key,url,options)
}

状态管理(useState/Pinia)、cookie管理(useCookie)

我们可以在项目的根目录新建composables中创建状态管理文件如:composables/state.ts.

useState的使用

内容封装:

//首先引入useState、useCookie
import { useState, useCookie } from "nuxt/app";
//用户详情
export const useInfo = () => useState("userData", () => { return { data: "",
    };
  });
//消息数量
export const messageNum = () => useState("msgNum", () => { return { data: 0,
    };
  });
// token
export const useToken = () => useState("token",()=> "aaadd232cfdfdf23fdf") 

pinia的使用

pinia使用

cookie管理(useCookie)

// 获取 Cookie
let tokenCookies = useCookie('token')
// 设置 Cookie
tokenCookies .value = Cookies.value || ''
// 删除  Cookie
tokenCookies .value = undefined || null

token续期

什么是续期呢?为了用户安全,token会出现失效的状态,一般为1~30天。根据华为云等的做法,可以测试出,为保障用户安全,一般token有效期为2H,在1.5h时,后端会将新的token塞入响应头中,再取出替换。

useFetch(url, { ...options,
        onResponse(ctx) { if(ctx.response.headers?.get('Authorizations')){ const Authorization = useCookie("cookies名称");
            Authorization.value = ctx.response.headers?.get('Authorizations')
          }
        }
      })
$fetch(url, { ...options,
        onResponse(ctx) { if(ctx.response.headers?.get('Authorizations')){ const Authorization = useCookie("cookies名称");
            Authorization.value = ctx.response.headers?.get('Authorizations')
          }
        }
      })