Vue 第1课:把接口数据渲染成页面

课程目标:Vue 把已经跑通的 Spring Boot 接口变成人能看的页面
预计时间:45 分钟
前置条件:第1课的 /hello/{name}/about 已能跑

回头看第1课

还记得第1课那几行 @RestController 吗?接口是有了,但浏览器打开的是一串 JSON,只有开发者看得懂。

比如访问 http://localhost:8080/about,你看到的是:

{"course":"Spring Boot","lesson":1,"author":"MiMo"}

这串数据对机器很友好,但对人来说不够直观。今天我们就用 Vue 把它变成一个漂亮的页面。

本课阅读方式: 正文里带彩色虚线下划线的名词,鼠标放上去就会弹出一个小窗, 里面是三段式① 官方定义(正式术语 + 英文全称)→ ② 一句话大白话③ 生活类比; 带用法的名词(比如各种 @ 注解)还会多一段 ④ 规范写法——可直接照抄的最小代码示例。 比如把鼠标放到 响应式 上试试。
每个名词只在第一次出现时带下划线,之后再出现只保留颜色,不再重复弹窗。 全部 69 个名词都记录在 名词速查笔记 GLOSSARY.md(带目录,可搜索)。 答疑和笔记都收在 DSH 笔记文档页

从 JSON 到页面:Vue 数据渲染之旅

① 为什么需要模板?

想象一下:你要在页面上显示 "课程:Spring Boot,第1课,作者:MiMo"。

如果用原生 JavaScript,你得这样写:

document.getElementById('course').textContent = data.course;
document.getElementById('lesson').textContent = data.lesson;
document.getElementById('author').textContent = data.author;

但用 Vue模板,你只需要:

<div>课程:{{ course }},第{{ lesson }}课,作者:{{ author }}</div>

模板就像一个填空题:数据变了,页面自动更新。

静态 HTML 页面引入 Vue 框架创建应用实例绑定数据到模板页面动态更新

② 最小可用三件套

不引入构建工具链,我们用最简单的方式:

index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Vue 数据渲染</title>
</head>
<body>
    <div id="app">
        <h1>{{ title }}</h1>
        <p>课程:{{ course }}</p>
    </div>
    <script type="importmap">
    {
        "imports": {
            "vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
        }
    }
    </script>
    <!-- 实际项目中这里引用你的 app.js -->
    <script type="module" src="app.js"></script>
</body>
</html>

app.js

import { createApp } from 'vue';
import { fetchAbout } from './api.js';

const app = createApp({
    data() {
        return {
            title: 'Vue 数据渲染',
            course: '',
            lesson: 0,
            author: ''
        };
    },
    async mounted() {
        const data = await fetchAbout();
        this.course = data.course;
        this.lesson = data.lesson;
        this.author = data.author;
    }
});

app.mount('#app');

api.js

export async function fetchAbout() {
    const response = await fetch('http://localhost:8080/about');
    return await response.json();
}

验证:打开 index.html,看到 "Vue 数据渲染" 和课程信息。

③ 响应式:数据变,页面变

Vue 的核心是 响应式系统。用 ref() 创建响应式数据:

import { ref } from 'vue';

const message = ref('Hello Vue');
// 模板中:{{ message }}
// 改值:message.value = 'Hi Vue';
// 页面自动更新!

试试:在输入框里打字,页面上的字当场跟着变。

<input v-model="message" />
<p>你输入了:{{ message }}</p>

这就是 v-model 的魔力:输入框和数据双向绑定。

④ 列表与条件:渲染数组

如果接口返回的是数组,用 v-for 渲染:

<ul>
    <li v-for="item in items" :key="item.id">
        {{ item.name }}
    </li>
</ul>

v-if 做三态(加载中 / 有数据 / 出错):

<div v-if="loading">加载中...</div>
<div v-else-if="error">出错了:{{ error }}</div>
<div v-else>{{ data }}</div>
加载中数据加载成功加载失败

⑤ 取数据:fetch + async/await

从 Spring Boot 接口获取数据:

async function loadData() {
    try {
        const response = await fetch('http://localhost:8080/about');
        const data = await response.json();
        // 把数据交给 ref
        course.value = data.course;
        lesson.value = data.lesson;
        author.value = data.author;
    } catch (err) {
        error.value = err.message;
    }
}

为什么页面会闪一下?

因为 await 前页面是空的,await 后数据才来。这就是为什么我们要做三态:先显示"加载中",数据来了再显示内容。

T1浏览器请求页面T2Vue 应用初始化T3fetch 调用 Spring Boot 接口T4返回 JSON 数据T5数据渲染到页面

⑥ 跨域这道墙

打开浏览器控制台,看到这个错误了吗?

Access to fetch at 'http://localhost:8080/about' 
from origin 'null' has been blocked by CORS policy

浏览器为了安全,不允许页面请求不同源的接口。

解决方法:在 Spring Boot 控制器上加 @CrossOrigin

@RestController
@CrossOrigin  // 加这一行
public class HelloController {
    // ...
}

重启 Spring Boot,刷新页面,控制台不再报错。

⑦ 常见错误对照表

错误现象 可能原因 解决方法
CORS 报错 没加 @CrossOrigin 在控制器上加注解
404 Not Found 端口写错(8080 vs 3000) 检查 fetch 的 URL
undefined 字段名拼错 对比 JSON 和模板
页面空白 忘了 mount('#app') 检查 app.js 最后一行

⑧ 小测验

Vue 的响应式系统用什么创建?

  • var
  • let
  • ref()
  • const

解决跨域问题要加什么注解?

  • @RestController
  • @CrossOrigin
  • @GetMapping
  • @RequestBody
全部 69 个名词(含前面课程内容)都在 GLOSSARY.md 里,带目录表格,可直接搜索。

推荐阅读(按优先级)

  1. Vue 官方文档:模板语法
  2. Vue 官方文档:响应式基础
  3. Vue 官方文档:列表渲染
  4. Spring 官方指南:CORS

课后挑战(做完再往下学)

  1. 最小可用三件套
    做:创建 index.html + app.js + api.js,用 importmap 引入 Vue,createApp 挂在 #app
    验收:打开页面看到一句话(可以是硬编码的"Hello Vue")
  2. 渲染 /about 接口
    做:调用第1课的 /about 接口,把 course / lesson / author 三个字段显示在页面上
    验收:页面显示 "课程:Spring Boot,第1课,作者:MiMo"
  3. 响应式输入框
    做:用 ref() 存输入值,v-model 绑输入框,页面实时显示输入内容
    验收:目视确认:输入框打字时页面同步变化,控制台无报错
  4. 拆掉跨域
    做:在 Spring Boot 控制器上加 @CrossOrigin,重启后刷新页面
    验收:目视确认:浏览器控制台里没有 "blocked by CORS policy" 错误