CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
Vue 3 核心/课时/数据获取
RawBlame
课时目录12 节

Vue 3 核心

  1. 01Vue 是什么
  2. 02项目创建与 SFC
  3. 03模板语法
  4. 04响应式基础
  5. 05组件与 Props
  6. 06计算属性与侦听
  7. 07组合式 API 深入
  8. 08Vue Router
  9. 09Pinia 状态管理
  10. 10数据获取
  11. 11构建与部署
  12. 12综合练习

数据获取

fetch、async setup、loading 状态。

30 分钟

数据获取

这一课你将能做到

  1. 在组件中用 fetch + 异步加载列表,并处理 loading / error / 空数据三态
  2. 在 onMounted 或 watch 路由参数时发起请求,并处理竞态
  3. 对照本站:UI 用前端框架,业务数据仍多来自 Spring Boot /api

为什么要学

真实页面几乎都要远程数据:课程列表、用户信息、提交结果。
不会管三态,就会白屏、闪错、或显示过期列表。Vue 不绑定特定请求库——fetch 或 axios 皆可;本课用 fetch 打底。

先建立图像

进入页面 / slug 变化
  → loading=true
  → fetch /api/...
  → 成功:写入 ref;失败:error 文案
  → loading=false
模板根据三态分支渲染
状态UI
loading骨架/文案「加载中」
error可重试提示
success 空「暂无数据」
success 有列表

跟着做

步骤 1:最小三态

<script setup>
import { ref, onMounted } from "vue";

const tracks = ref([]);
const loading = ref(false);
const error = ref("");

async function load() {
  loading.value = true;
  error.value = "";
  try {
    const res = await fetch("/api/tracks");
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    tracks.value = await res.json();
  } catch (e) {
    error.value = e.message || "加载失败";
  } finally {
    loading.value = false;
  }
}

onMounted(load);
</script>

<template>
  <p v-if="loading">加载中…</p>
  <p v-else-if="error">
    {{ error }}
    <button type="button" @click="load">重试</button>
  </p>
  <p v-else-if="tracks.length === 0">暂无课程</p>
  <ul v-else>
    <li v-for="t in tracks" :key="t.id || t.slug">{{ t.title }}</li>
  </ul>
</template>

本地若无 /api/tracks,会走 error 分支——正好练习重试 UI。可用 JSON Placeholder 或 Vite 代理到本站后端。

步骤 2:Vite 代理(可选)

// vite.config.js
export default {
  server: {
    proxy: {
      "/api": "http://localhost:8080",
    },
  },
};

指向本机 Spring Boot,与 React/Next 课 同一数据源思想。

步骤 3:随路由参数重新加载

<script setup>
import { watch } from "vue";
import { useRoute } from "vue-router";
const route = useRoute();
watch(
  () => route.params.slug,
  (slug) => {
    if (slug) loadTrack(slug);
  },
  { immediate: true }
);
</script>

组件被复用时,仅 onMounted 不够——必须 watch 参数。

步骤 4:竞态守卫

let seq = 0;
async function loadTrack(slug) {
  const my = ++seq;
  loading.value = true;
  try {
    const res = await fetch(`/api/tracks/${slug}`);
    const data = await res.json();
    if (my !== seq) return; // 过期响应丢弃
    track.value = data;
  } finally {
    if (my === seq) loading.value = false;
  }
}

快速切换路由时,旧请求后返回不该覆盖新页。

步骤 5:抽 useFetchList composable(可选)

把 loading/error/data/load 推进 composable,多页复用——衔接上一课。

步骤 6:对照 React

React 课用 useEffect 取数;Vue 用 onMounted/watch。
两边都要:依赖变化重取、清理/竞态、三态 UI。本站真相在 Boot,不在前端内存。

讲清楚要点

  1. fetch 不把 404 当 throw:要自己查 res.ok。
  2. JSON 解析失败也进 catch。
  3. 凭证与 cookie:跨域要 CORS;同源代理更省事。
  4. 别把 token 写死进仓库;用环境变量。
  5. 列表与详情接口分离:对齐本站 track list vs lesson content。
  6. 错误信息对人话:HTTP 500 可再映射成「服务暂不可用」。

你可能会懵的地方

  • 为什么有时开发成功、生产失败?
    代理只在 dev;生产需同源或正确 API 域名。

  • axios 要不要?
    团队统一即可;会 fetch 就够迁移。

  • Suspense?
    Vue 3 支持异步组件悬停;入门先显式三态更直观。

  • POST 提交?
    同模式:method:'POST', headers, body;仍要错误处理。

  • 和 Pinia?
    缓存可进 store,但要定失效;先会组件内取数。

错法对照

错法问题正解
只写成功路径白屏难查三态齐全
忽略 res.ok把错误 HTML 当 JSON检查状态码
只 onMounted 不 watch 参数路由切换数据旧watch slug
无竞态处理显示错页数据序号/AbortController
前端写死业务规则当唯一校验不安全后端再验
把 Boot 重写成一堆 mock 就算完成假完成至少对接一次真 API 或明确 mock 边界

自测三问

  1. 三态分别对应什么 UI?
  2. 为何 res.ok 必须检查?
  3. 路由参数变化时如何避免竞态?

小结一句话

用 fetch 拉远端数据时,把 loading/error/空/成功写全,并在路由变化与快速切换下保持结果正确。

官方延伸

  • MDN fetch
  • 下一课:构建与部署
加载本节练习…
← 上一课Pinia 状态管理下一课 →构建与部署