uni-app 网络请求与后端交互完全指南:从基础到实战

发布于:2025-08-29 ⋅ 阅读:(16) ⋅ 点赞:(0)

在移动应用开发中,网络请求是连接前端与后端的核心桥梁,也是实现数据动态展示、用户交互的关键环节。作为跨平台开发框架的佼佼者,uni-app 提供了一套统一的网络请求方案,既能适配多端(App、小程序、H5 等),又能满足复杂业务场景的需求。本文将从基础用法入手,逐步深入到实战技巧,帮助你彻底掌握 uni-app 与后端的交互逻辑。

一、uni-app 网络请求的核心 API:uni.request ()

uni-app 并未引入额外的第三方库(如 axios),而是内置了 uni.request() 方法作为网络请求的统一入口。该方法遵循 Promise 规范,同时兼容回调函数写法,适配所有支持的平台,无需针对不同端做额外适配。

1. 基本语法与参数说明

uni.request() 的核心参数如下(仅列出常用关键参数):

参数名 类型 说明 必选
url String 后端接口地址(需注意跨域问题)
method String 请求方法,可选值:GET/POST/PUT/DELETE 等 否(默认 GET)
data Object/String/ArrayBuffer 请求参数(GET 会拼接到 URL,POST 会放在请求体)
header Object 请求头(如 Content-Type、Token 等)
success Function 请求成功的回调(返回数据在 res.data 中)
fail Function 请求失败的回调(如网络错误、超时等)
complete Function 请求完成的回调(无论成功 / 失败都会执行)

2. 最简单的 GET 请求案例

以 “获取用户信息” 接口为例,演示基础的 GET 请求:

// 发起 GET 请求获取用户信息
uni.request({
  url: 'https://api.example.com/user/info', // 后端接口地址
  method: 'GET',
  data: {
    userId: '123456', // 传递给后端的参数
    token: 'abcdef123456'
  },
  success: (res) => {
    // 请求成功:res 为后端返回的完整数据
    console.log('用户信息请求成功', res.data);
    // 通常后端会返回 code(状态码)、message(提示信息)、data(业务数据)
    if (res.data.code === 200) {
      // 业务成功:处理数据(如赋值给页面变量)
      this.userInfo = res.data.data;
    } else {
      // 业务失败:提示用户
      uni.showToast({
        title: res.data.message,
        icon: 'none'
      });
    }
  },
  fail: (err) => {
    // 请求失败:如网络断开、接口不存在等
    console.error('用户信息请求失败', err);
    uni.showToast({
      title: '网络错误,请稍后重试',
      icon: 'none'
    });
  }
});

3. 常用的 POST 请求案例

POST 请求常用于提交数据(如登录、表单提交),需注意 headerContent-Type 的配置(后端通常要求 application/jsonapplication/x-www-form-urlencoded):

// 发起 POST 请求实现用户登录
uni.request({
  url: 'https://api.example.com/user/login',
  method: 'POST',
  header: {
    'Content-Type': 'application/json' // 明确请求体格式为 JSON
  },
  data: {
    username: 'test123',
    password: '123456'
  },
  success: (res) => {
    if (res.data.code === 200) {
      // 登录成功:存储 Token(后续请求需携带)
      uni.setStorageSync('token', res.data.data.token);
      // 跳转到首页
      uni.switchTab({
        url: '/pages/index/index'
      });
    } else {
      uni.showToast({
        title: res.data.message || '登录失败',
        icon: 'none'
      });
    }
  },
  fail: () => {
    uni.showToast({
      title: '网络异常,登录失败',
      icon: 'none'
    });
  }
});

二、实战优化:封装请求工具,避免重复代码

在实际项目中,每个接口都写一次 uni.request() 会导致代码冗余(如重复处理 Token、错误提示、请求头)。因此,封装请求工具是必做的优化步骤,既能提高效率,又能统一管理请求逻辑。

1. 封装思路

  1. 统一配置基础路径(如 baseURL),避免每次写完整 URL;

  2. 自动携带 Token(从本地存储中获取);

  3. 统一处理请求头(如 Content-Type);

  4. 统一拦截错误(如 Token 过期、网络错误);

  5. 支持 Promise 链式调用,方便异步处理。

2. 完整的请求工具封装代码

在项目根目录下创建 utils/request.js 文件,代码如下:

// utils/request.js
const request = (options) => {
  // 1. 基础配置:统一 baseURL(区分开发/生产环境)
  const baseURL = process.env.NODE_ENV === 'development' 
    ? 'https://dev.api.example.com' // 开发环境接口
    : 'https://api.example.com';    // 生产环境接口

  // 2. 合并请求参数:默认方法为 GET,默认请求头为 JSON
  const config = {
    url: baseURL + options.url,
    method: options.method || 'GET',
    header: {
      'Content-Type': 'application/json',
      // 自动携带 Token(若本地有存储)
      'Authorization': uni.getStorageSync('token') ? `Bearer ${uni.getStorageSync('token')}` : ''
    },
    data: options.data || {}
  };

  // 3. 返回 Promise,支持链式调用
  return new Promise((resolve, reject) => {
    uni.request({
      ...config,
      success: (res) => {
        // 4. 统一处理后端返回的状态码
        const { code, message, data } = res.data;
        
        // Token 过期:清除本地存储,跳转到登录页
        if (code === 401) {
          uni.removeStorageSync('token');
          uni.navigateTo({
            url: '/pages/login/login'
          });
          reject(new Error('Token 已过期,请重新登录'));
          return;
        }

        // 业务成功:返回核心数据
        if (code === 200) {
          resolve(data);
        } else {
          // 业务失败:提示错误信息,拒绝 Promise
          uni.showToast({
            title: message || '请求失败',
            icon: 'none'
          });
          reject(new Error(message || '请求失败'));
        }
      },
      fail: (err) => {
        // 5. 统一处理网络错误
        uni.showToast({
          title: '网络错误,请稍后重试',
          icon: 'none'
        });
        reject(err);
      }
    });
  });
};

// 6. 暴露常用请求方法(GET/POST),简化调用
export default {
  get(url, data) {
    return request({ url, method: 'GET', data });
  },
  post(url, data) {
    return request({ url, method: 'POST', data });
  },
  put(url, data) {
    return request({ url, method: 'PUT', data });
  },
  delete(url, data) {
    return request({ url, method: 'DELETE', data });
  }
};

3. 封装后如何使用?

在页面或组件中引入工具,调用方式极大简化:

// 在页面中引入请求工具
import request from '@/utils/request';

export default {
  data() {
    return {
      userList: []
    };
  },
  onLoad() {
    // 调用 GET 方法获取用户列表
    this.getUserList();
  },
  methods: {
    async getUserList() {
      try {
        // 链式调用:直接获取后端返回的核心数据(无需再处理 code)
        const data = await request.get('/user/list', {
          page: 1,
          size: 10
        });
        // 业务处理
        this.userList = data;
      } catch (err) {
        // 错误处理(可选,工具已统一提示)
        console.error('获取用户列表失败', err);
      }
    },

    async doLogin() {
      try {
        // 调用 POST 方法提交登录数据
        const data = await request.post('/user/login', {
          username: 'test123',
          password: '123456'
        });
        // 登录成功:存储 Token(工具后续会自动携带)
        uni.setStorageSync('token', data.token);
        uni.switchTab({ url: '/pages/index/index' });
      } catch (err) {
        // 无需额外提示(工具已处理)
      }
    }
  }
};

三、关键问题解决:跨域、Token 与超时

在 uni-app 与后端交互过程中,跨域、Token 管理、超时处理是最常见的问题,下面逐一给出解决方案。

1. 跨域问题:仅存在于 H5 端

跨域是浏览器的安全策略,仅在 H5 端会出现(App、小程序端不限制跨域)。解决方式有两种:

方式 1:后端配置 CORS(推荐)

让后端在响应头中添加允许跨域的配置,例如(以 Node.js Express 为例):

// 后端代码:允许所有域名跨域(生产环境需指定具体域名)
app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  next();
});
方式 2:uni-app 配置代理(开发环境临时方案)

manifest.json 的 H5 配置中添加代理,将请求转发到后端地址,避免跨域:

// manifest.json -> "h5" 节点
"h5": {
  "devServer": {
    "proxy": {
      "/api": { // 匹配前端请求的 /api 前缀
        "target": "https://dev.api.example.com", // 后端真实地址
        "changeOrigin": true, // 开启跨域
        "pathRewrite": { // 重写路径(可选)
          "^/api": "" // 如前端请求 /api/user/list,实际转发到 https://dev.api.example.com/user/list
        }
      }
    }
  }
}

2. Token 管理:身份验证的核心

Token 是后端识别用户身份的凭证,通常在登录后获取,后续请求需携带。除了在封装工具中自动携带 Token,还需注意以下几点:

  • Token 存储:使用 uni.setStorageSync('token', token) 存储(同步),或 uni.setStorage(异步);

  • Token 过期处理:在请求工具的 success 回调中拦截 code: 401(Token 过期),清除本地 Token 并跳转到登录页;

  • Token 刷新:复杂场景下,可通过 “刷新 Token” 接口获取新 Token(需存储刷新 Token),避免用户重新登录。

3. 超时处理:避免请求无限等待

uni.request() 中添加 timeout 参数(单位:毫秒),设置请求超时时间,超时后会触发 fail 回调:

// 在封装工具的 config 中添加超时配置
const config = {
  // ...其他参数
  timeout: 10000, // 10秒超时
};

四、高级技巧:请求拦截与响应拦截

如果需要更灵活的请求控制(如添加加载动画、日志打印),可以在封装工具中增加 “请求拦截” 和 “响应拦截” 逻辑。

1. 请求拦截:发起请求前的处理

在请求发送前,可添加加载动画(如 uni.showLoading)、打印请求日志等:

// 在 request 函数中,发起请求前添加拦截
const request = (options) => {
  // ...基础配置

  // 请求拦截:显示加载动画
  uni.showLoading({
    title: '加载中...',
    mask: true // 防止用户点击其他区域
  });

  return new Promise((resolve, reject) => {
    uni.request({
      ...config,
      success: (res) => {
        // ...成功处理
      },
      fail: (err) => {
        // ...失败处理
      },
      complete: () => {
        // 无论成功/失败,都关闭加载动画
        uni.hideLoading();
      }
    });
  });
};

2. 响应拦截:获取响应后的统一处理

除了之前的错误拦截,还可添加日志打印(如记录请求耗时、返回数据):

// 在 success 回调中添加响应拦截
success: (res) => {
  // 打印响应日志(开发环境)
  if (process.env.NODE_ENV === 'development') {
    console.log(`[响应] ${config.url}:`, res.data);
  }

  // ...后续状态码处理
}

五、总结

uni-app 与后端的交互核心是 uni.request() 方法,通过封装工具可以大幅提升开发效率,统一处理请求逻辑。本文从基础用法到实战优化,覆盖了请求封装、跨域解决、Token 管理、高级拦截等关键知识点,掌握这些内容后,你可以轻松应对大多数业务场景。

最后提醒:实际开发中,需与后端明确接口文档(如请求方法、参数格式、返回状态码),避免因接口不统一导致的问题。如果需要处理更复杂的场景(如文件上传、WebSocket),可进一步学习 uni-app 的 uni.uploadFile()uni.connectSocket() 方法。


网站公告

今日签到

点亮在社区的每一天
去签到