Nuxt3 fetch请求封装,用户登录状态全局管理

请求封装

在composables文件夹下新建useHttp.ts

import { ElMessage } from 'element-plus'
import type { FetchResponse, SearchParameters } from 'ofetch'


export interface ResOptions<T> {
  data: T
  code: number
  message: string
  success: boolean
}

const handleError = <T>(response: FetchResponse<ResOptions<T>> & FetchResponse<ResponseType>) => {
  const err = (text: string) => {
    ElMessage.error(response?._data?.message ?? text)
  }
  if (!response._data) {
    err('请求超时,服务器无响应!')
    return
  }
  const userStore = useUserStore()
  const handleMap: { [key: number]: () => void } = {
    404: () => err('服务器资源不存在'),
    500: () => err('服务器内部错误'),
    403: () => err('没有权限访问该资源'),
    401: () => {
      err('登录状态已过期,需要重新登录')
      userStore.value.userInfo = null
      // TODO 跳转实际登录页
      navigateTo('/login')
    },
  }
  handleMap[response.status] ? handleMap[response.status]() : err('未知错误!')
}

// get方法传递数组形式参数
const paramsSerializer = (params?: SearchParameters) => {
  if (!params)
    return

  const query = params
  Object.entries(query).forEach(([key, val]) => {
    if (typeof val === 'object' && Array.isArray(val) && val !== null) {
      query[`${key}[]`] = toRaw(val).map((v: any) => JSON.stringify(v))
      delete query[key]
    }
  })
  return query
}


const fetch = $fetch.create({
  // 请求拦截器
  onRequest({ options }) {
    // get方法传递数组形式参数
    options.params = paramsSerializer(options.params)
    // 添加baseURL,nuxt3环境变量要从useRuntimeConfig里面取
    const { public: { apiBase } } = useRuntimeConfig()
    options.baseURL = apiBase
    // 添加请求头,没登录不携带token
    const userStore = useUserStore()
    if (!userStore.value.isLogin)
      return
    options.headers = new Headers(options.headers)
    options.headers.set('Authorization', `Bearer ${userStore.value.getToken()}`)
  },
  // 响应拦截
  onResponse({ response }) {
    if (response.status === 200){
        return response
    }else{
        handleError(response)
        return Promise.reject(response._data)
    }
    // 成功返回
    return response._data
  },
  // 错误处理
  onResponseError({ response }) {
    handleError(response)
    return Promise.reject(response?._data ?? null)
  },
})

// 自动导出
export const useHttp = {
  get: <T>(url: string, params?: any) => {
    return fetch<T>(url, { method: 'get', params })
  },

  post: <T>(url: string, body?: any) => {
    return fetch<T>(url, { method: 'post', body })
  },

  put: <T>(url: string, body?: any) => {
    return fetch<T>(url, { method: 'put', body })
  },

  delete: <T>(url: string, body?: any) => {
    return fetch<T>(url, { method: 'delete', body })
  },
}

用户登录状态管理

import { login } from '~/api/login'

interface user{
    /**是否登录 */
    isLogin: Boolean,
    /**获取保存的token */
    getToken: Function,
    /**保存token */
    setToken: Function,
    /**用户信息 */
    userInfo: any,
    /**用户登录 */
    login: Function,
    /**获取用户信息 */
    getCurrentUser: Function,
    /**退出登录 */
    logout: Function,
}
export const useUserStore = () =>  useState<user>('useUserStore',()=>({
        isLogin:false,
        getToken: ()=>{
           return localStorage.getItem('token')
        },
        setToken: (e: string)=>{
            localStorage.setItem('token',e)
        },
        userInfo: {},
        login:(e: Object)=>{
            return loginApi(e)
        },
        getCurrentUser:()=>{
            getUserInfo()
        },
        logout:()=>{
            logout()
        }
    })
)

// 获取用户信息
function getUserInfo(){
    useUserStore().value.isLogin = true
    useUserStore().value.userInfo = {
        name: '张三',
        age: 18
    }
}

// 退出登录
function logout(){
    useUserStore().value.isLogin = false
    useUserStore().value.userInfo = {}
    localStorage.removeItem('token')
}

// 登录
function loginApi(e: Object) {
    return new Promise((resolve, reject) => {
        login(e).then((result: any) => {
            resolve(result)
        }).catch((err: any) => {
            reject(err)
        });
    })
}

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值