从零打造 AI 全栈应用(五):Post List 背后的前后端解耦与 Mock 工程化实践

10 阅读4分钟

在上一篇《从零打造 AI 全栈应用(四):别小看幻灯片,一个 Carousel 组件背后的工程化与性能思维一、为什么一个幻灯片组件》 中,我们通过一个轮播组件,拆解了组件状态、插件模式与性能取舍

这一篇,我们把视角从「组件内部」拉回到「页面级数据流」,聊一个在真实项目中几乎绕不开的问题

前端页面的数据,到底该怎么来?


一、Post List 是 UI 问题,还是数据问题?

在很多博客 / 社区 / AI 内容产品中,都会有一个核心页面:

文章列表(Post List)

表面上它是一个 UI:

  • 卡片列表
  • 分页
  • 点赞数 / 评论数 / 标签

但工程上,它首先是一个数据协作问题

  • 数据来自哪里?
  • 前端要不要等后端?
  • 后端接口没好,页面怎么办?

如果这几个问题想不清楚,项目一定会出现:

  • 前端被后端接口卡进度
  • 大量 if (data) 防御式代码
  • 开发阶段和线上环境差异巨大

二、前后端分离的核心前提:前端不能等后端

很多同学嘴上说前后端分离,但心智模型还是:

「等后端接口写好,我再写页面」

这是不成立的

真正的前后端分离,意味着:

  • 前端可以独立完成页面与交互
  • 后端只要遵守接口契约即可无缝接入

而这个“契约”,就是 —— API 接口文档


三、先定义接口,而不是先写代码

以 Post List 为例,我们先约定接口形态:

GET /api/posts?page=1&limit=10

返回结构:

{
  "code": 200,
  "items": Post[],
  "pagination": {
    "current": 1,
    "limit": 10,
    "total": 45,
    "totalPage": 5
  }
}

注意这里的几个工程化点:

  • 分页信息由后端返回,不是前端猜
  • 字段命名稳定,不夹杂 UI 语义
  • 返回结构对 mock / 真接口完全一致

只要这个结构不变,
前端切换真实后端地址是无感的


四、Mock 的工程意义,而不是“假数据”

很多人一听 mock,就觉得是:

随便造点数据糊页面

这是对 mock 的严重低估。

在工程中,mock 的作用是:

  • 解耦前后端开发节奏
  • 固化接口结构
  • 提前暴露分页 / 边界问题
  • 让前端在真实请求语义下开发

五、Vite + vite-plugin-mock:最小成本接入

pnpm i vite-plugin-mock -D

它的优势在于:

  • 与 Vite 深度集成
  • 开发环境自动启用
  • 不侵入业务代码

上线前只需要切换 baseURL,
mock 即可完全下线。


六、Post Mock 的核心不是数据,而是「逻辑完整度」

1️⃣ 使用 Mock.js 构造真实数据结构

const posts = Mock.mock({
  'list|45': [{
    title: '@ctitle(8, 20)',
    brief: '@ctitle(20,100)',
    totalComment: '@integer(0, 30)',
    totalLikes: '@integer(0, 500)',
    publishedAt: '@datetime("yyyy-MM-dd HH:mm")',
    user: {
      id: '@integer(1, 10)',
      name: '@cname(2, 4)',
      avatar: '@image(300x200)'
    },
    tags: () => Mock.Random.pick(tags, 2),
    thumbnail: '@image(300x200)',
    id: '@increment(1)'
  }]
}).list;

重点不在“随机”,而在:

  • 字段类型是否稳定
  • 嵌套结构是否真实
  • 是否足够支撑 UI 复杂度

2️⃣ 分页逻辑必须和真实后端一致

const currentPage = parseInt(page, 10);
const size = parseInt(limit, 10);

const start = (currentPage - 1) * size;
const end = start + size;
const paginatedData = posts.slice(start, end);

以及返回的 pagination:

pagination: {
  current: currentPage,
  limit: size,
  total,
  totalPage: Math.ceil(total / size)
}

如果 mock 不做分页,
那前端分页逻辑一定会在真接口时翻车。


七、Axios:前端的“数据适配层”

前端通过 axios 请求接口,本质上并不关心:

  • 数据是真是假
  • 接口来自 mock 还是真后端

它只关心:

  • 返回结构是否符合约定
  • 错误码是否可控

这也是为什么:

mock 必须 100% 模拟真实接口语义


八、顺带一提:Auth Mock 是怎么服务页面的?

登录 mock 使用 JWT:

  • login:签发 token
  • check:验证 token

这带来的好处是:

  • 前端可以完整开发登录态逻辑
  • 请求拦截器、权限判断全部可写
  • 不等真实用户系统

九、回到工程视角:这一篇你真正学到什么?

通过一个 Post List,你应该能讲清楚:

  • 什么是“前端不能等后端”
  • mock 在工程中的真实价值
  • 分页为什么必须由接口驱动
  • 如何设计一个可无缝切换的 API 层

面试官真正关心的不是你会不会用 mock,
而是你是否具备前后端协作的工程意识