封装api方法(全面)

1. 封装的目的

2.基础准备

复制代码
pnpm add axios
# 若需要处理 TypeScript 类型(可选),额外安装
pnpm add @types/axios -D

3.封装通用请求实例(仅参考)

复制代码
// 引入 axios
import axios from 'axios'

// 1. 创建 axios 实例,配置基础参数
const service = axios.create({
  // 基础请求地址:区分开发/生产环境(关键!避免打包后修改地址)
  baseURL: process.env.NODE_ENV === 'development' 
    ? 'http://localhost:8080/api'  // 开发环境(后端本地/测试服务器地址)
    : 'https://prod-api.xxx.com/api', // 生产环境(线上服务器地址)
  // 请求超时时间:超过该时间未响应,视为请求失败
  timeout: 10000,
  // 统一请求头(可选,根据后端要求配置)
  headers: {
    'Content-Type': 'application/json;charset=utf-8'
  }
})

// 2. 请求拦截器:发送请求前做的处理(如添加 token、修改请求参数格式)
service.interceptors.request.use(
  (config) => {
    // 【常见场景 1】添加用户登录 token(后端需要身份验证时)
    // 从 uni-app 本地存储中获取 token(登录后存入)
    const token = uni.getStorageSync('userToken')
    if (token) {
      // 给请求头添加 token,字段名(Authorization)按后端要求修改(如 token、X-Token)
      config.headers.Authorization = `Bearer ${token}`
    }

    // 【常见场景 2】如果是 GET 请求,统一处理参数格式(可选)
    // if (config.method === 'get') {
    //   config.params = { ...config.params } // 可添加额外公共参数,如 timestamp: Date.now()
    // }

    // 【常见场景 3】如果是上传文件(FormData 格式),修改请求头
    // if (config.data instanceof FormData) {
    //   config.headers['Content-Type'] = 'multipart/form-data'
    // }

    return config
  },
  (error) => {
    // 请求发送失败(如网络中断、配置错误)的处理
    console.error('请求发送失败:', error)
    return Promise.reject(error)
  }
)

// 3. 响应拦截器:收到后端响应后做的处理(如统一解析数据、处理错误码)
service.interceptors.response.use(
  (response) => {
    // 取出后端返回的核心数据(一般后端会返回 { code: 200, data: {}, msg: '成功' } 格式)
    const res = response.data

    // 【常见场景 1】统一处理成功响应:只返回核心 data,简化接口调用
    if (res.code === 200 || res.code === 0) { // 后端成功码按实际约定修改(200/0 最常用)
      return res.data // 后续接口调用时,直接拿到 data 数据,无需再解构
    }

    // 【常见场景 2】统一处理业务错误(如参数错误、token 过期、无权限)
    else {
      // 1. 弹出错误提示(uni-app 内置提示框)
      uni.showToast({
        title: res.msg || '请求失败',
        icon: 'none',
        duration: 2000
      })

      // 2. 特殊错误码单独处理(如 token 过期,跳转登录页)
      if (res.code === 401) { // 401 一般代表未登录/token 过期
        uni.showModal({
          title: '提示',
          content: '登录状态已过期,请重新登录',
          showCancel: false,
          success: () => {
            // 清除本地 token,跳转登录页
            uni.removeStorageSync('userToken')
            uni.redirectTo({ url: '/pages/login/login' })
          }
        })
      }

      // 3. 把错误抛出去,便于接口调用时单独处理(可选)
      return Promise.reject(new Error(res.msg || '业务请求失败'))
    }
  },
  (error) => {
    // 【常见场景 3】处理网络错误/服务器错误(如 404、500、请求超时)
    console.error('响应处理失败:', error)
    const errMsg = error.message || '网络异常,请稍后重试'
    
    // 弹出错误提示
    uni.showToast({
      title: errMsg,
      icon: 'none',
      duration: 2000
    })

    return Promise.reject(error)
  }
)

// 4. 导出封装好的 axios 实例,供后续接口调用
export default service

4.api封装接口在不同情况下如何写

基于上面封装的 request 实例,按业务模块拆分接口(如用户模块、商品模块),每个接口对应后端的一个接口地址。
只需配置「请求方法、接口路径、请求参数」即可。
参数传递

  1. GET请求用params:参数自动拼在URL后,适合少量查询参数
  2. POST/PUT请求用data:参数放在请求体中,适合传递大量提交/更新数据
  3. 路径参数(如/{id}):直接用反引号拼写在url中
    每个接口返回 request(...)/http(...):本质是返回一个 Promise 对象,后续调用时可使用 async/await 或 .then()

处理。

统一步骤

复制代码
// 引入封装好的 axios 实例
import request(http) from '@/utils/request'

第一种方法

复制代码
// 【用户模块接口】

// 场景 1:GET 请求(查询数据,参数拼在 URL 上)
// 示例:获取用户信息(后端接口:GET /user/info,参数:userId(可选,从 token 解析也可))
export const getUserInfo = (userId) => {
  return request({
    method: 'GET',
    url: '/user/info', // 接口路径(拼接在 baseURL 后面,完整地址:baseURL + /user/info
    params: { userId } // GET 请求参数:会自动拼在 URL 后,格式:?userId=xxx
  })
}

第二种方法

复制代码
// 场景 2:POST 请求(提交数据,参数放在请求体中)
// 示例:用户登录(后端接口:POST /user/login,参数:username、password)
export const userLogin = (data) => {
  return request({
    method: 'POST',
    url: '/user/login',
    data: data // POST 请求参数:放在请求体中,格式为 JSON(对应 request.js 中的 Content-Type)
  })
}

第三种方法

复制代码
// 场景 3:PUT 请求(更新数据,全量更新)
// 示例:修改用户昵称(后端接口:PUT /user/nickname,参数:userId、nickname)
export const updateUserNickname = (data) => {
  return request({
    method: 'PUT',
    url: '/user/nickname',
    data: data
  })
}

第四种方法

复制代码
// 场景 4:DELETE 请求(删除数据)
// 示例:删除用户地址(后端接口:DELETE /user/address/{addressId},参数:addressId(路径参数))
export const deleteUserAddress = (addressId) => {
  return request({
    method: 'DELETE',
    url: `/user/address/${addressId}` // 路径参数:直接拼接在 URL 中(注意用反引号 ``)
  })
}

第五种方法

复制代码
// 场景 5:上传文件(FormData 格式,需配合 request.js 中的请求头修改)
// 示例:上传用户头像(后端接口:POST /user/avatar)
export const uploadUserAvatar = (file) => {
  // 创建 FormData 实例
  const formData = new FormData()
  // 添加文件(字段名 'avatar' 按后端要求修改)
  formData.append('avatar', file)
  // 发起请求
  return request({
    method: 'POST',
    url: '/user/avatar',
    data: formData,
    // 覆盖默认请求头(对应 request.js 中的注释场景 3)
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  })
}

5. 在 页面/组件中调用接口

导入接口→调用接口→处理返回数据

复制代码
<template>
  <view class="login-container">
    <input v-model="username" placeholder="请输入用户名" />
    <input v-model="password" type="password" placeholder="请输入密码" />
    <button @click="handleLogin">登录</button>
  </view>
</template>

<script setup>
import { ref } from 'vue'
// 方式 1:直接从模块导入(适合接口较少时)
import { userLogin } from '@/api/user'
// 方式 2:从统一导出文件导入(适合接口较多时)
// import { userLogin } from '@/api'

// 定义表单数据
const username = ref('')
const password = ref('')

// 登录按钮点击事件
const handleLogin = async () => {
  // 1. 表单验证(可选,前端先做基础校验,减少无效请求)
  if (!username.value || !password.value) {
    uni.showToast({ title: '请输入用户名和密码', icon: 'none' })
    return
  }

  try {
    // 2. 调用封装的登录接口,传递参数(对象格式,对应后端要求)
    const res = await userLogin({
      username: username.value,
      password: password.value
    })

    // 3. 处理接口返回数据(res 就是后端返回的 res.data,已在 request.js 中处理)
    console.log('登录成功,用户信息:', res)
    // 存储 token 到本地(供后续接口请求使用)
    uni.setStorageSync('userToken', res.token)
    // 跳转首页
    uni.switchTab({ url: '/pages/index/index' })
  } catch (error) {
    // 4. 处理接口调用失败(如业务错误、网络错误,也可省略,因为 request.js 已做统一提示)
    console.error('登录失败:', error)
  }
}
</script>

6.遇到不同的后端接口(适配改动)

1
后端接口场景 :基础地址变更
对应的修改位置 :utils/request.js 的 baseURL
具体操作 :直接修改开发 / 生产环境的地址即可;若有多环境(测试 / 预发布),可新增环境变量配置。

2
后端接口场景 :身份验证字段不是 Authorization
对应的修改位置 :utils/request.js 请求拦截器
具体操作 :把 config.headers.Authorization 改为后端要求的字段,如 config.headers.token。

3
后端接口场景 :响应成功码不是 200/0
对应的修改位置 :utils/request.js 响应拦截器
具体操作 :把 res.code === 200/res.code === 0改为后端约定的成功码,如res.code === 20000

4
后端接口场景 :响应格式不是 {code, data, msg}
对应的修改位置 :utils/request.js 响应拦截器
具体操作 :调整 res 的解构方式,比如后端返回 {success: true, result: {}, message: ''},则修改为:if (res.success) { return res.result }

5
后端接口场景 :需要传递 FormData 上传文件
对应的修改位置 :具体接口(如 api/user.js)
具体操作 :创建 FormData 实例,添加文件 / 参数,覆盖请求头为 multipart/form-data。

6
后端接口场景 :接口需要跨域(开发环境)
对应的修改位置 :uni-app 项目根目录创建 vite.config.js
具体操作 :配置 vite 代理,转发请求,避免跨域错误(下面补充)。

7.补充:开发环境跨域解决方案(vite 代理)

如果开发时出现「Access to XMLHttpRequest at ... from origin ... has been blocked by CORS policy」跨域错误,可在项目根目录创建 vite.config.js,配置代理转发:

复制代码
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'

export default defineConfig({
  plugins: [uni()],
  server: {
    proxy: {
      // 匹配所有以 /api 开头的请求路径
      '/api': {
        target: 'http://localhost:8080', // 后端真实接口地址(去掉 /api)
        changeOrigin: true, // 开启跨域模拟
        rewrite: (path) => path.replace(/^\/api/, '') // 重写路径:去掉 /api 前缀(根据后端接口是否带 /api 调整)
      }
    }
  }
})
相关推荐
游戏开发爱好者82 小时前
iPhone 网络调试的过程,请求是否发出,是否经过系统代理,app 绕过代理获取数据
android·网络·ios·小程序·uni-app·iphone·webview
一殊酒2 小时前
【前端开发】Vue项目多客户配置自动化方案【二】
javascript·vue.js·自动化
Mr Xu_2 小时前
深入解析 getBoundingClientRect 与 offsetTop:解决 Vue 平滑滚动偏移误差问题
前端·javascript·vue.js
Mr-Wanter2 小时前
vue 解决img图片路径存在但图片无法访问时显示错误的问题
前端·vue·img
muddjsv2 小时前
近些年前端开发主流技术全景:趋势、工具与实践指南
前端
沛沛老爹2 小时前
从Web到AI:多模态Agent Skills开发实战——JavaScript+Python全栈赋能视觉/语音能力
java·开发语言·javascript·人工智能·python·安全架构
贾修行2 小时前
Kestrel:.NET 的高性能 Web 服务器探秘
服务器·前端·kestrel·.net·net core·web-server·asp.net-core
吃吃喝喝小朋友2 小时前
HTML DOM
前端·javascript·html