【Uni-App+SSM 宠物项目实战】Day8:Uni-App 网络请求

79 阅读9分钟

一、前言

经过前 7 天的开发,我们已经有了能返回数据的后端接口(Day7 的宠物列表接口)和初始化完成的前端 Uni-App 项目(Day4),今天终于要实现 “前后端数据打通”——用 Uni-App 发送网络请求,把后端的宠物数据渲染到前端页面上

Uni-App 中发送网络请求,我们会用 Axios(一个轻量的 HTTP 请求库,像 “快递员” 一样帮前端把请求送到后端,再把数据带回来)。为了避免每次请求都写重复代码,我们先封装一个request.js工具文件;同时,前后端分离项目很容易遇到 “跨域问题”(就像不同小区之间的 “通行限制”),今天也会教大家用后端配置彻底解决这个问题。

即使你是第一次用 Axios 也不用慌,我们从 “安装→封装→调用” 一步步来,每段代码都带详细注释,确保你能跟着做出来。

二、今日教学目标

  1. 掌握 Uni-App 中 Axios 的安装与封装(request.js),避免重复编写请求代码;
  1. 学会在 Vue 页面中调用后端接口(Day7 的/chongwuxinxi/list),并渲染宠物列表数据;
  1. 理解跨域问题的原因,能用后端CORSConfig配置解决跨域报错。

三、前置准备

  1. 已完成 Day7 内容:后端/chongwuxinxi/list接口能正常返回数据(用 Postman 测试通过);
  1. 已打开 Uni-App 项目(front目录),且 HBuilder X 已安装 “终端” 插件(用于执行 npm 命令);
  1. 安装 Axios:
    • 在 HBuilder X 中,右键front项目→选择 “在终端中打开”;
    • 输入命令npm install axios,按下回车(等待安装完成,项目会新增node_modules文件夹)。

四、代码实现(核心:请求封装 + 调用 + 跨域解决)

1. 第一步:封装 Axios 请求(request.js)

为了方便后续所有接口调用(比如后续的商家接口、订单接口),我们先封装一个request.js,统一配置后端地址、超时时间、请求拦截器等。

(1)创建request.js文件

路径:C:\Users\骆\Downloads\my-pet-custom\mypet\src\main\webapp\front\api\request.js(手动创建api文件夹,用于存放所有请求工具)。

(2)编写封装代码

// 导入安装好的Axios
import axios from 'axios';
// 创建Axios实例:相当于“定制一个专属快递员”,统一配置请求规则
const service = axios.create({
  baseURL: 'http://localhost:8080', // 后端项目的基础地址(固定,所有接口都基于这个地址拼接)
  timeout: 5000, // 请求超时时间:5秒内没响应就报错(避免一直等)
  headers: {
    'Content-Type': 'application/json;charset=utf-8' // 请求头:告诉后端数据格式是JSON
  }
});
// 请求拦截器:发送请求前的“预处理”(比如后续加登录Token)
service.interceptors.request.use(
  (config) => {
    // 这里可以加后续需要的Token(比如用户登录后,把Token放在请求头里)
    // 示例:config.headers.Authorization = 'Bearer ' + uni.getStorageSync('token');
    return config; // 必须返回config,否则请求发不出去
  },
  (error) => {
    // 请求发送失败时的处理(比如网络错误)
    console.error('请求发送失败:', error);
    return Promise.reject(error);
  }
);
// 响应拦截器:收到后端响应后的“预处理”(比如统一处理错误)
service.interceptors.response.use(
  (response) => {
    // 只返回后端的核心数据(response.data才是后端返回的JSON,去掉外层包装)
    return response.data;
  },
  (error) => {
    // 响应失败时的处理(比如接口报错、超时)
    console.error('接口响应失败:', error);
    // 可以加弹窗提示用户(Uni-App的弹窗API)
    uni.showToast({
      title: '请求失败,请稍后再试',
      icon: 'none',
      duration: 2000
    });
    return Promise.reject(error);
  }
);
// 导出封装好的Axios实例,供其他页面调用
export default service;

2. 第二步:在 Vue 页面中调用接口(渲染宠物列表)

我们在 “宠物” Tab 对应的页面(pages/pet/index.vue)中调用接口,把后端返回的宠物数据渲染到页面上。

(1)打开 / 创建 Vue 页面

路径:C:\Users\骆\Downloads\my-pet-custom\mypet\src\main\webapp\front\pages\pet\index.vue(如果没有,新建pet文件夹和index.vue)。

(2)编写页面代码(模板 + 脚本)

<template>
  <!-- 页面容器:Uni-App的基础布局标签 -->
  <view class="pet-list-container">
    <!-- 标题 -->
    <view class="page-title">宠物列表</view>
    
    <!-- 宠物列表:用v-for循环渲染每一条宠物数据 -->
    <view class="pet-item" v-for="(pet, index) in petList" :key="index">
      <!-- 宠物名称 -->
      <view class="pet-name">名称:{{ pet.mingcheng }}</view>
      <!-- 宠物品种 -->
      <view class="pet-breed">品种:{{ pet.pinzhong }}</view>
      <!-- 宠物年龄 -->
      <view class="pet-age">年龄:{{ pet.nianling }}</view>
    </view>
    
    <!-- 空数据提示:如果petList为空,显示“暂无宠物数据” -->
    <view class="empty-tip" v-if="petList.length === 0">
      暂无宠物数据
    </view>
  </view>
</template>
<script>
// 导入封装好的request.js(请求工具)
import request from '@/api/request.js';
export default {
  // 页面数据:存放宠物列表
  data() {
    return {
      petList: [] // 初始为空数组,接口返回数据后赋值
    };
  },
  
  // 页面生命周期:onLoad在页面加载时执行(只执行一次)
  onLoad() {
    // 调用“获取宠物列表”的方法
    this.getPetList();
  },
  
  // 页面方法:存放自定义逻辑
  methods: {
    // 获取宠物列表:调用后端接口
    getPetList() {
      // 用封装的request发送GET请求,地址是“后端基础地址 + /chongwuxinxi/list”
      request.get('/chongwuxinxi/list')
        .then((res) => {
          // 请求成功:res是后端返回的核心数据(响应拦截器已处理)
          console.log('获取宠物列表成功:', res);
          // 把后端返回的数据赋值给petList,页面会自动渲染
          this.petList = res;
        })
        .catch((err) => {
          // 请求失败:捕获错误(比如跨域、接口报错)
          console.error('获取宠物列表失败:', err);
        });
    }
  }
};
</script>
<style scoped>
/* 页面样式:用scoped确保样式只作用于当前页面 */
.pet-list-container {
  padding: 20rpx; /* Uni-App推荐用rpx做单位,适配不同屏幕 */
}
.page-title {
  font-size: 32rpx;
  font-weight: bold;
  margin-bottom: 30rpx;
}
.pet-item {
  background-color: #fff;
  padding: 20rpx;
  border-radius: 16rpx;
  margin-bottom: 20rpx;
  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); /* 轻微阴影,更美观 */
}
.pet-name, .pet-breed, .pet-age {
  font-size: 28rpx;
  margin-bottom: 10rpx;
  color: #333;
}
.empty-tip {
  font-size: 28rpx;
  color: #999;
  text-align: center;
  margin-top: 100rpx;
}
</style>

3. 第三步:解决跨域问题(后端配置CORSConfig)

如果直接运行前端页面,浏览器控制台会报 “Access to XMLHttpRequest at 'http://localhost:8080/chongwuxinxi/list' from origin 'http://localhost:8081' has been blocked by CORS policy”(跨域错误),原因是前端(比如 H5 端口 8081)和后端(端口 8080)“域名 / 端口不同”,浏览器出于安全限制拦截了请求。

解决方法:在后端添加 CORS 配置,允许前端跨域请求。

(1)创建CORSConfig.java文件

路径:src/main/java/com/config/CORSConfig.java(后端项目的 config 包下)。

(2)编写跨域配置代码

package com.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
 * 跨域配置类:解决前后端分离的跨域问题
 */
@Configuration // 标记为Spring配置类,项目启动时自动加载
public class CORSConfig implements WebMvcConfigurer {
    /**
     * 配置跨域规则
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 对所有接口生效(/**表示所有路径)
                .allowedOrigins("*") // 允许所有前端来源(开发环境用*,生产环境可指定具体域名,如"http://www.mypet.com")
                .allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的请求方法(GET查询、POST提交等)
                .allowedHeaders("*") // 允许所有请求头(比如Token、Content-Type)
                .maxAge(3600L); // 预检请求的有效期(1小时,避免频繁发送预检请求)
    }
}

五、效果验证

1. 启动后端项目

  1. 打开 IDEA,重启后端项目(确保CORSConfig生效);
  1. 用 Postman 再次测试/chongwuxinxi/list接口,确认能正常返回数据。

2. 运行 Uni-App 前端项目(H5 端)

  1. 在 HBuilder X 中,右键front项目→选择 “运行→运行到浏览器→Chrome”;
  1. 浏览器自动打开前端页面,切换到 “宠物” Tab(底部 TabBar):
    • 若后端有数据,页面会显示每条宠物的 “名称、品种、年龄”;
    • 若后端无数据,页面显示 “暂无宠物数据”;
    • 打开浏览器控制台(F12),在 “Console” 面板能看到 “获取宠物列表成功” 的日志。

3. 小程序端验证(可选)

  1. 在 HBuilder X 中,右键front项目→选择 “运行→运行到小程序模拟器→微信开发者工具”;
  1. 微信开发者工具加载完成后,切换到 “宠物” Tab,同样能看到宠物列表数据(跨域配置对小程序也生效)。

六、常见问题与解决方案

问题描述可能原因解决方案
浏览器控制台报 “CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource”后端未添加CORSConfig配置,或配置未生效1. 确认CORSConfig.java已放在com.config包下;2. 检查类上是否加了@Configuration注解;3. 重启后端项目(配置类需重启生效)
前端报 “Request failed with status code 404”1. request.js中的baseURL错误(比如多写了项目名,如http://localhost:8080/mypet);2. 接口路径写错(如/chongwuxi/list少写 “n”)1. 确认baseURL是http://localhost:8080(与后端 Tomcat 端口一致);2. 检查接口路径是否与后端@RequestMapping一致(后端是/chongwuxinxi/list,前端不能错)
前端页面无数据,控制台报 “Cannot read property 'data' of undefined”1. Axios 请求未进入then,直接进入catch(比如后端接口报错);2. 后端返回数据格式不是数组(比如返回{code:200, data:[]},但响应拦截器没处理)1. 查看控制台 “接口响应失败” 的错误日志,定位后端问题;2. 检查request.js的响应拦截器:若后端返回格式是{code:200, data:[]},需修改拦截器为return response.data.data;(取内层 data)
HBuilder X 终端执行npm install axios报错 “npm command not found”HBuilder X 未配置 Node.js 环境(npm 是 Node.js 的包管理工具)1. 下载安装 Node.js(官网:nodejs.org/,安装时勾选 “Add to PATH”);2. 重启 HBuilder X,重新打开终端执行命令

七、工具类 / 框架特性拓展

1. request.js封装的好处

  • 避免重复代码:如果有 10 个接口,不用每个接口都写axios.create、超时时间、错误处理;
  • 统一维护:后续需要加登录 Token、修改后端地址,只需改request.js一处,所有接口都生效;
  • 错误统一处理:接口报错时,不用每个页面都写弹窗提示,响应拦截器统一弹 “请求失败”。

2. 跨域问题的本质与生产环境配置

  • 本质:浏览器的 “同源策略”(协议、域名、端口三者必须一致,否则拦截请求),比如前端http://localhost:8081(端口 8081)和后端http://localhost:8080(端口 8080)属于 “不同端口”,触发跨域;
  • 生产环境配置:开发环境用allowedOrigins("*")方便,但生产环境为了安全,需指定具体前端域名,比如:
.allowedOrigins("http://www.mypet.com", "https://mypet-app.com") // 只允许官网和App的前端域名跨域

八、结语

今天我们成功实现了 “前后端数据打通”—— 你的前端页面能正常显示宠物列表吗?

如果遇到跨域错误、接口 404、数据不渲染等问题,欢迎在评论区分享:

  • 浏览器控制台的错误截图(关键部分打码);
  • 你的request.js中baseURL配置和接口路径;

我们一起分析问题,确保大家都能搞定 “网络请求” 这个关键步骤!