在nuxt3里useFetch封装一个api接口http请求

2022-03-31 16:54
椰子皮
19388
22
32
nuxt

在nuxt3里useFetch封装一个api接口http请求

2023-04-04基于nuxt3.3.3更新

nuxt3使用了ts和vue3,nuxt3的使用下来,体验还是很不错的,那么如何在nuxt3里面封装一个http请求呢

相关文档:https://nuxt.com.cn/docs/api/composables/use-fetch

 

新建一个http.ts

以下是基于rc.8以上版本增加了createError,错误可以在error.vue中展示

import { hash } from 'ohash'

// 后端返回的数据类型
export interface ResOptions<T> {
  data: T
  code?: number
  message?: string
}

/**
 * api请求封装
 * @param { String } url 请求地址
 * @param { Object } options useFtech第二个参数
 * @param { Object } headers 自定义header头, 单独设置headers区分请求参数,也好设置类型
 */
const fetch = async (url: string, options?: any, headers?: any) => {

  try {
    // 3.0正式版环境变量要从useRuntimeConfig里的public拿
    const { public: { VITE_API_HOST } } = useRuntimeConfig()
    const reqUrl = VITE_API_HOST + url // 你的接口地址

    // 设置key
    const key =  hash(JSON.stringify(options) + url)

    // 可以设置默认headers例如,token的获取最好用useState返回一个useCookie
    const customHeaders = { token: useToken().value, ...headers }

    const { data, error } = await useFetch(reqUrl, { ...options, key, headers: customHeaders })
    const result = data.value as ResOptions<any>
    console.log('useFetchResData: ', result)
    if (error.value || !result || (result && result.code !== 200)) {
      // 处理token失效的情况
      if (code === 401) {
        // token.value = ''
        await navigateTo('/login')
      }
      // 在客户端的时候抛出错误结果方便捕捉
      if (process.client) {
        return Promise.reject(result || error.value)
      }
      // 在服务端就直接渲染错误页面,需要设置一个error.vue接收错误信息
      throw createError({
        statusCode: 500,
        statusMessage: reqUrl,
        message: error.value?.message || '服务器内部错误',
      })
    }
    return result.data // 这里直接返回data或者其他的
  } catch (err) {
    console.log(err)
    return Promise.reject(err)
  }

}

export default class Http {

  get(url: string, params?: any, headers?: any) {
    return fetch(url, { method: 'get', params }, headers)
  }

  post(url: string, body?: any, headers?: any) {
    return fetch(url, { method: 'post', body }, headers)
  }

  put(url: string, body?: any, headers?: any) {
    return fetch(url, { method: 'put', body }, headers)
  }

  delete(url: string, body?: any, headers?: any) {
    return fetch(url, { method: 'delete', body }, headers)
  }
}

 

新建一个api文件夹,新建一个index.ts,其他的根据业务模块新建文件,index.ts用于导出其他模块,如图:

 

比如我想把文章相关的api都写在一个文件里,我们可以利用到js的继承,让api代码可读性更高,例如可以在article.ts里面写:

import Http from '@/utils/http'

export default new class article extends Http {

  /**
   * 获取热门文章,自定义返回类型可以通过Promise<T>设置,不设置就是any
   */
  public getHot(): Promise<{ items: Array<{ id: number, name: string }>}> {
    return this.get('/app/v1/article/hotView')
  }

  /**
   * 获取文章详情
   * @param { Number } id 文章id
   */
  public getDetail(id: number) {
    return this.get('/app/v1/article/detail/' + id)
  }
}

如果类型太多,可以在api里面再建一个types,里面放对应模块的.d.ts类型

 

api/index.ts导出这些模块:

import articleApi from '@/api/article'

export default {
  articleApi,
}

 

composables/index.ts中:

import api from '@/api/index'

export const useApi = () => api

 

然后页面中使用:

<script lang="ts" setup>
const { articleApi } = useApi()
// 返回的数据结构根据自己后端在api文件定义好,这里建议直接等于返回结果,不用再去定义类型了
const hots = await articleApi.getHot({ page: 1, size: 50 })
console.log(hots.items)

</script>

 

 

支付宝微信
32
关注公众号获取更多内容
nuxt3+vue3+typescript里写一个全局提示框toast插件
结合lazyload实现文章页里面的图片预加载
共有 22 条评论
发表评论
  • 666#10125
    2023-10-19 15:34
    北京市北京市海淀区
    Mac OS 10.15.7
    Chrome

    类里的函数可以写成静态方法,这样就不用 new了

  • 111#10123
    2023-08-10 10:22
    四川省乐山市
    Windows 10
    Chrome

    code === 401 这里的code是什么意思,哪里来的呀

    椰子皮2022-03-27 回复@111
    后端返回给你的code
  • freezyh#10121
    2023-07-31 09:40
    广东省广州市天河区
    Windows 10
    Chrome

    useFetch 里面的配置选项key 好像起不来了作用,有和没有效果都一样,博主能举个例子么

  • rachel#10120
    2023-07-05 16:19
    上海市上海市普陀区
    Mac OS 10.15.7
    Chrome

    用了这个封装方法,刷新页面,报错 Error: A composable that requires access to the

  • lagaga#10119
    2023-06-25 14:47
    四川省成都市武侯区
    Windows 10
    Chrome

    setup顶层处理await,你如何抛错呢?

    椰子皮2022-03-27 回复@lagaga
    加try catch不就行了,你也可以再写个函数内部处理错误,再顶层await这个函数
  • creepre#10118
    2023-05-06 14:06
    云南省昆明市西山区
    Windows 10
    Chrome

    Http是构造函数,不new就能访问里面的方法?

    椰子皮2022-03-27 回复@creepre
    需要new,感谢指正,已修改
  • 前端ss#10117
    2023-04-27 16:57
    北京市北京市东城区
    Windows 10
    Chrome

    首屏从后台请求数据渲染以后,页面通过@绑定的事件都没有被绑定,是什么原因?你们没有出现么?用官方原始写法不会

    椰子皮2022-03-27 回复@前端ss
    就是客户端js被阻塞了吧,有个相关配置可以解决服务端加载太久
  • carefree#10116
    2023-04-12 13:43
    福建省福州市
    Windows 10
    Chrome

    有没有能隐藏后端请求api地址的方法

    椰子皮2022-03-27 回复@carefree
    没有,异步都会被看到的,自己再加密就可以了
  • nuxt3#10115
    2023-04-09 17:09
    湖北省武汉市
    Mac OS 10.15.7
    Chrome

    您好,使用useFetch方法去请求, 默认是混合模式(ssr、csr),部署到生产后,首次请求该页面(或是刷新后),请求都为404;但是再从其他页面跳转到此页面(此时是csr吧),请求都正常。请教您问题可能出在哪里

    椰子皮2022-03-27 回复@nuxt3
    检查请求是否在顶级await,就是要服务端渲染这个请求必须是顶级await
  • HELLO#10114
    2023-03-02 10:16
    广东省深圳市南山区
    Windows 10
    Chrome

    请问需要请求第三方服务器,怎么配置才不会跨域呢?

    椰子皮2022-03-27 回复@HELLO
    可以通过后端接口进行转发一下,或者直接用nuxt的server里面用node封装一个接口
总共 22
  • 1
  • 2
  • 3
不支持canvas
春季
夏季
秋季
冬季
暗黑
简约
小清新