您现在的位置是:首页 >技术交流 >nuxt3.0学习-二、nuxt3.0的请求相关内容、状态管理(useState/Pinia)、cookie管理(useCookie)、token续期网站首页技术交流

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

久居我心你却从未交房租 2024-06-01 00:00:03
简介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')
          }
        }
      })
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。