手把手教你在 Taro 小程序中用 axios 替代 Taro.request:@tarojs/plugin-http 配置与拦截器封装
在 Taro 开发微信小程序时,Taro.request 是官方提供的网络请求方法,但用过的同学都知道,它缺乏拦截器、Promise 链优化等实用特性。而 axios 作为前端开发者熟悉的 HTTP 库,不仅支持这些特性,还能复用我们已有的封装逻辑。不过直接在 Taro 中用 axios 会有环境适配问题,这时候 @tarojs/plugin-http 插件就能派上用场 ------ 它能让 axios 完美适配小程序环境,帮我们替代 Taro.request。
这篇文章会手把手带你完成整个流程:从项目初始化,到插件配置、axios 拦截器封装,再到实际接口调用,每一步都有具体代码和操作说明,新手也能轻松跟上。
一、为什么要替代 Taro.request?先搞懂核心优势
在开始操作前,先明确 "用 axios 替代 Taro.request" 的价值,避免为了替代而替代:
- 拦截器能力:axios 支持请求 / 响应拦截器,能统一处理 Token 添加、错误提示(比如 401 未登录跳转),不用在每个请求里重复写逻辑;
- Promise 链优化:axios 原生支持 Promise,写法更优雅,比如 axios.get().then().catch(),比 Taro.request 的回调式写法更直观;
- 功能更丰富:支持请求取消(防止重复点击)、请求 / 响应数据转换(比如自动解析 JSON)、超时重连等,这些 Taro.request 都需要手动封装;
- 复用性更强:如果你的项目同时开发 H5 和小程序,axios 封装可以跨端复用,不用为 Taro.request 单独写一套逻辑。
而 @tarojs/plugin-http 的作用,就是解决 axios 在小程序中 "水土不服" 的问题 ------ 因为 axios 底层依赖浏览器的 XMLHttpRequest,而小程序环境没有这个对象,插件会帮我们做适配,让 axios 能正常发起小程序的网络请求。
二、环境准备:从 0 搭好 Taro 项目
首先我们需要一个 Taro 项目(以 Taro 4.x + React + JavaScript 为例,其他版本流程类似),如果已有项目可以跳过这一步。
1. 安装 Taro CLI
打开终端,执行以下命令全局安装 Taro 脚手架: npm install -g @tarojs/cli
安装完成后,执行 taro -v 能看到版本号(比如 4.1.7),说明安装成功。
2. 新建 Taro 小程序项目
执行 taro init 命令创建项目,按提示选择配置:
csharp
taro init taro-axios-demo
配置选择如下(新手建议按这个选,避免踩坑):
- 项目名称:默认 taro-axios-demo 即可;
- 框架:选择 React(如果用 Vue 也可以,后续代码调整对应语法即可);
- 语言:选择 JavaScript(TS 版本后续可自行调整);
- 微信小程序 AppID:如果没有,选 "测试号" 即可(开发阶段不影响);
- 其他选项(是否使用 TypeScript、ESLint 等):新手建议选 "否",先聚焦核心功能。
3. 安装核心依赖
进入项目目录,安装 axios 和 @tarojs/plugin-http:
bash
cd taro-axios-demo
npm install axios @tarojs/plugin-http --save
安装完成后,打开 package.json,能在 dependencies 里看到这两个依赖,说明安装成功:
perl
"dependencies": {
"axios": "^1.6.8",
"@tarojs/plugin-http": "^3.6.32",
// 其他依赖...
}
三、关键步骤 1:配置 @tarojs/plugin-http 插件
插件需要在 Taro 配置文件中注册,才能生效。打开项目根目录的 config/index.js,做以下修改:
1. 注册插件
在 plugins 数组中添加 @tarojs/plugin-http,表示启用这个插件:
java
// config/index.js
module.exports = {
projectName: "taro-axios-demo",
date: "2025-10-13",
designWidth: 750,
deviceRatio: {
640: 2.34 / 2,
750: 1,
828: 1.81 / 2
},
// 1. 注册 http 插件(关键步骤)
plugins: [
'@tarojs/plugin-http' // 就是这行,不能写错
],
// 其他默认配置...
};
2. 配置插件参数
在 pluginConfig 中添加 http 配置,设置接口基础路径、超时时间等全局参数(后续 axios 会用到这些配置):
java
// config/index.js(接上面的代码)
module.exports = {
// 前面的配置...
// 2. 配置 http 插件参数(关键步骤)
pluginConfig: {
http: {
baseURL: '域名', // 你的接口基础域名
timeout: 10000, // 请求超时时间(单位:毫秒)
headers: {
'Content-Type': 'application/json' // 默认请求头(JSON 格式)
}
}
},
// 后面的配置(framework、compiler 等)...
};
这里的 baseURL 很重要 ------ 后续我们写接口路径时,不用再写完整域名,比如接口 baidu.com/api/list,只需写 /api/list 即可,axios 会自动拼接 baseURL。
四、关键步骤 2:封装 axios 拦截器(核心中的核心)
这一步是 "替代 Taro.request" 的核心 ------ 我们要封装 axios 的请求 / 响应拦截器,统一处理 Token、错误提示等逻辑,避免在每个请求里重复写代码。
在 src 目录下新建 utils 文件夹,再在里面新建 request.js 文件(这个文件就是我们的 axios 封装工具):
1. 基础结构:创建 axios 实例
首先导入 axios 和 Taro,然后根据插件配置创建 axios 实例:
javascript
// src/utils/request.js
import axios from 'axios';
import Taro from '@tarojs/taro';
// 1. 创建 axios 实例(使用插件配置的参数)
const service = axios.create({
baseURL: '你的域名', // 和 pluginConfig.http 保持一致
timeout: 10000, // 超时时间(和插件配置一致)
headers: {
'Content-Type': 'application/json' // 默认请求头
}
});
这里为什么不直接用插件配置的参数,而是重新写一遍?因为 Taro 4.x 移除了 getPluginConfig 方法,直接读取插件配置会报错,所以我们手动保持一致即可(后续如果要改,只需改这里和 config/index.js 两处)。
2. 请求拦截器:统一添加 Token
请求拦截器的作用是 ------ 在请求发出去之前,做一些统一处理,比如添加 Token(登录态)。大部分接口都需要 Token 验证,这里我们从 Taro 缓存中获取 Token,添加到请求头:
javascript
// src/utils/request.js(接上面的代码)
// 2. 请求拦截器:添加 Token、处理请求参数
service.interceptors.request.use(
(config) => {
// 从 Taro 缓存中获取 Token(登录后会存入缓存)
const token = Taro.getStorageSync('userToken');
// 如果有 Token,添加到请求头(格式按你的接口要求来,这里是 Bearer Token)
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config; // 返回处理后的配置
},
(error) => {
// 请求出错时的处理(比如参数错误)
console.error('请求拦截器错误:', error);
// 提示用户
Taro.showToast({
title: '请求参数错误',
icon: 'none', // 不显示图标
duration: 2000 // 提示时长(毫秒)
});
return Promise.reject(error); // 把错误抛出去,方便后续处理
}
);
3. 响应拦截器:统一处理错误和数据
响应拦截器的作用是 ------ 在拿到接口返回数据后,做一些统一处理,比如:
- 如果接口返回错误(比如 401 未登录、403 无权限),统一提示用户;
- 如果接口返回成功,直接提取核心数据(过滤外层的 success、code 等字段)。
继续在 request.js 中添加响应拦截器:
javascript
// src/utils/request.js(接上面的代码)
// 3. 响应拦截器:统一处理错误、提取数据
service.interceptors.response.use(
(response) => {
// 接口返回的原始数据(response.data 是接口返回的 JSON)
const res = response.data;
// 假设你的接口返回格式是:{ success: boolean, data: any, code: number, message: string }
// 如果 success 是 true,说明请求成功,返回核心数据(res.data)
if (res.success) {
return res.data; // 后续调用接口时,拿到的就是这个 data
} else {
// 如果 success 是 false,说明业务错误(比如参数错误、权限不足)
handleBusinessError(res.code, res.message); // 专门的错误处理函数
return Promise.reject(res); // 抛错,让后续的 catch 能捕获到
}
},
(error) => {
// 网络错误(比如超时、断网、域名错误)
console.error('响应拦截器错误:', error);
// 判断错误类型(超时还是其他)
const errorMsg = error.message?.includes('timeout')
? '请求超时,请稍后重试'
: '网络异常,请检查网络';
// 提示用户
Taro.showToast({
title: errorMsg,
icon: 'none',
duration: 2000
});
return Promise.reject(error); // 抛错,方便后续处理
}
);
4. 封装业务错误处理函数
上面用到了 handleBusinessError 函数,专门处理接口返回的业务错误(比如 401 未登录),我们在响应拦截器下面定义这个函数:
php
// src/utils/request.js(接上面的代码)
// 4. 业务错误处理函数(根据你的接口错误码调整)
const handleBusinessError = (code, message) => {
switch (code) {
case 400003: // 假设 400003 是"未登录"的错误码
Taro.showToast({
title: message || '请先登录',
icon: 'none',
duration: 2000
});
// 跳转到登录页(登录后可以返回当前页,这里简化处理)
Taro.navigateTo({
url: '/pages/login/index' // 你的登录页路径
});
break;
case 403: // 假设 403 是"无权限"的错误码
Taro.showToast({
title: message || '你没有操作权限',
icon: 'none',
duration: 2000
});
break;
default: // 其他错误
Taro.showToast({
title: message || '操作失败',
icon: 'none',
duration: 2000
});
break;
}
};
这里的错误码(比如 400003、403)需要根据你的实际接口文档调整,不要直接抄我的!
5. 封装 get/post 方法(方便调用)
最后,我们封装 get 和 post 方法,让后续调用接口时更简洁:
javascript
// src/utils/request.js(接上面的代码)
// 5. 封装 get/post 方法(对外暴露)
export default {
// get 请求:params 是 URL 参数(比如 ?id=1&name=test)
get(url, params = {}, config = {}) {
return service.get(url, { params, ...config });
},
// post 请求:data 是请求体参数(JSON 格式)
post(url, data = {}, config = {}) {
return service.post(url, data, config);
}
};
这样,后续我们调用接口时,只需写 request.get('/api/xxx') 或 request.post('/api/xxx', data) 即可,非常简洁。
五、关键步骤 3:调用接口(实战演示)
封装好 axios 后,我们来实战调用一个接口(你项目中的接口) ------ 例如: baiodu.com/api/list(获取用户权限)为例,演示如何在页面中使用。
1. 按业务模块封装接口(推荐做法)
在 src 目录下新建 api 文件夹,再新建 account.js 文件(按业务模块分文件,比如 account 对应账号相关接口),里面定义我们的接口函数:
javascript
// src/api/account.js
// 导入封装好的 axios 工具
import request from '../utils/request';
/**
* 获取用户权限列表接口
* 完整地址:baseURL + /api/list
* @returns {Promise} 权限列表数据
*/
export const getPermissions = () => {
// 调用 get 方法(因为这个接口是 GET 类型)
return request.get('/api/account/getPermissions');
};
// 如果你有其他账号相关接口,也可以在这里添加,比如登录接口:
// export const login = (data) => {
// return request.post('/api/account/login', data);
// };
2. 在页面中调用接口
以首页(src/pages/index/index.jsx)为例,我们在页面加载时调用 getPermissions 接口,获取权限列表并展示:
第一步:页面代码结构
javascript
// src/pages/index/index.jsx
import React, { useState, useEffect } from 'react';
import { View, Text, Button, ScrollView } from '@tarojs/components';
import Taro from '@tarojs/taro';
// 导入接口函数
import { getPermissions } from '../../api/account';
// 导入样式(后面会写)
import './index.scss';
export default function Index() {
// 状态管理:权限列表、加载状态
const [permissions, setPermissions] = useState([]);
const [loading, setLoading] = useState(false);
// 页面加载时调用接口( useEffect 模拟生命周期)
useEffect(() => {
fetchPermissions();
}, []);
// 调用接口的函数(async/await 写法,更直观)
const fetchPermissions = async () => {
try {
// 开始加载:设置 loading 为 true
setLoading(true);
// 调用接口(这里拿到的是响应拦截器处理后的核心数据)
const data = await getPermissions();
// 接口成功:更新权限列表状态
setPermissions(data || []);
// 提示用户成功
Taro.showToast({
title: '获取权限成功',
icon: 'success', // 显示成功图标
duration: 1500
});
} catch (error) {
// 接口失败:重置权限列表(错误提示在响应拦截器已经处理了)
setPermissions([]);
console.error('获取权限失败:', error);
} finally {
// 结束加载:不管成功还是失败,都设置 loading 为 false
setLoading(false);
}
};
// 页面渲染
return (
<View className="index-container">
<Text className="page-title">用户权限列表</Text>
{/* 刷新按钮(可以重新调用接口) */}
<Button
className="refresh-btn"
loading={loading} // 加载时显示loading状态
onClick={fetchPermissions} // 点击重新调用接口
>
{loading ? '加载中...' : '刷新权限'}
</doubaocanvas>