从零开始构建一个现代化前端项目:GitHub + React + Spring Boot 全栈入门指南

Vue快乐水
2025-12-16 00:24
阅读 374

大家好,我是小码哥,在某大厂做了三年前端开发,平时也在B站分享技术教程。今天想和大家聊聊“如何从零开始搭建一个现代化的前端项目”。为什么写这篇教程?因为我当初学的时候,面对 GitHub、React、后端接口这些概念,真的是一头雾水——不知道从哪下手,也不知道它们怎么连起来用。现在回头看,其实只要有人带你走一遍流程,很多“神秘感”就消失了。

这篇文章专为完全零基础的同学设计。不需要你懂 JavaScript,也不需要你会 Java,只要你有一台电脑,愿意动手敲代码,就能跟着一步步完成一个前后端分离的小项目!


一、这个技术栈是干什么的?

我们常说的“现代化前端项目”,通常指:

  • 前端(用户看到的部分):用 React 构建界面
  • 后端(处理数据和逻辑):用 Spring Boot 提供 API 接口
  • 代码托管与协作:用 GitHub 存放和管理代码

简单来说:

用户在浏览器里操作 React 页面 → React 向 Spring Boot 后端发请求 → 后端返回数据 → React 展示给用户

这种“前后端分离”的架构是当前互联网公司的主流做法,也是你求职时几乎必考的内容。


二、环境准备:5 分钟搭好开发环境

别担心,这些工具都是免费的!按顺序安装即可。

1. 安装 Node.js(前端运行环境)

React 依赖 Node.js。去官网 https://nodejs.org 下载 LTS 版本(长期支持版),一路默认安装就行。

验证是否成功:

node -v  # 应输出类似 v18.x.x
npm -v   # 应输出类似 9.x.x

💡 小贴士:npm 是 Node 的包管理器,相当于“软件商店”,用来安装 React 等工具。

2. 安装 Java 17 + Maven(后端运行环境)

Spring Boot 需要 Java 17(目前最稳定的 LTS 版本)。

Maven 是 Java 的构建工具,Spring Initializr 会自动生成,暂时不用单独装。

3. 安装 Git + 注册 GitHub 账号

⚠️ 安全提醒:不要把密码、API 密钥等敏感信息提交到 GitHub! 我们后面会教你怎么避免。

4. 选择一个代码编辑器

推荐使用 VS Code(免费、轻量、插件多):

  • 下载地址:https://code.visualstudio.com
  • 安装后建议装两个插件:
    • ESLint(代码规范检查)
    • Prettier(自动格式化代码)

三、核心概念:用大白话解释专业术语

术语 通俗解释 类比
GitHub 代码的“网盘+协作平台” 像百度网盘,但专门存代码,还能多人一起改
React 构建用户界面的 JavaScript 库 像乐高积木,把页面拆成小块(组件)拼起来
Spring Boot 快速开发 Java 后端的框架 像厨房里的预制菜包,省去切菜洗菜步骤
API 前后端沟通的“协议” 像餐厅点菜单:前端说“我要一份牛肉面”,后端做好端上来

🌟 关键理解:前端负责“展示”,后端负责“干活”。它们通过 API(通常是 JSON 格式的数据)对话。


四、实战项目:做一个“待办事项”应用

我们要做一个简单的 Todo List:能添加任务、标记完成、删除任务。

步骤 1:创建 GitHub 仓库(代码存放地)

  1. 登录 GitHub
  2. 点右上角 +New repository
  3. 仓库名填 my-todo-app,选 Public(公开)
  4. 不要勾选 “Add a README”(我们本地初始化)
  5. Create repository

记下页面上的 HTTPS 地址,比如:

https://github.com/你的用户名/my-todo-app.git

步骤 2:搭建 React 前端

打开终端(Windows 用 PowerShell,Mac 用 Terminal),执行:

# 创建项目文件夹
mkdir my-todo-app
cd my-todo-app

# 用 Vite 创建 React 项目(比 Create React App 更快)
npm create vite@latest frontend -- --template react
cd frontend
npm install

# 启动开发服务器
npm run dev

浏览器打开 http://localhost:5173,看到 Vite 的欢迎页就成功了!

💡 为什么用 Vite?因为它启动快、热更新快,适合新手体验流畅开发。

修改 App.jsx 实现基础功能

替换 frontend/src/App.jsx 内容:

import { useState } from 'react'

function App() {
  const [todos, setTodos] = useState([])
  const [input, setInput] = useState('')

  const addTodo = () => {
    if (input.trim()) {
      setTodos([...todos, { id: Date.now(), text: input, done: false }])
      setInput('')
    }
  }

  const toggleTodo = (id) => {
    setTodos(todos.map(todo =>
      todo.id === id ? { ...todo, done: !todo.done } : todo
    ))
  }

  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id))
  }

  return (
    <div style={{ padding: '20px', maxWidth: '500px', margin: '0 auto' }}>
      <h1>我的待办事项</h1>
      
      <div style={{ display: 'flex', gap: '10px', marginBottom: '20px' }}>
        <input
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyPress={(e) => e.key === 'Enter' && addTodo()}
          placeholder="输入任务..."
          style={{ flex: 1, padding: '8px' }}
        />
        <button onClick={addTodo} style={{ padding: '8px 16px' }}>添加</button>
      </div>

      <ul style={{ listStyle: 'none', padding: 0 }}>
        {todos.map(todo => (
          <li key={todo.id} style={{
            padding: '10px',
            borderBottom: '1px solid #eee',
            display: 'flex',
            justifyContent: 'space-between'
          }}>
            <span
              onClick={() => toggleTodo(todo.id)}
              style={{
                textDecoration: todo.done ? 'line-through' : 'none',
                cursor: 'pointer'
              }}
            >
              {todo.text}
            </span>
            <button onClick={() => deleteTodo(todo.id)}>删除</button>
          </li>
        ))}
      </ul>
    </div>
  )
}

export default App

现在你的前端已经能本地运行了!但数据刷新就没了——因为没连后端。

步骤 3:搭建 Spring Boot 后端

回到项目根目录(my-todo-app),创建后端:

cd ..

访问 https://start.spring.io,填写:

  • Project: Maven
  • Language: Java
  • Spring Boot: 最新稳定版(如 3.2.x)
  • Group: com.example
  • Artifact: backend
  • Dependencies: 勾选 Spring WebSpring Data JPA + H2 Database(内存数据库,免配置)

Generate 下载 ZIP,解压到 my-todo-app/backend 文件夹。

编写 Todo 实体类

backend/src/main/java/com/example/backend 下新建 Todo.java

package com.example.backend;

import jakarta.persistence.*;

@Entity
@Table(name = "todos")
public class Todo {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String text;
    private boolean done;

    // 必须有空构造函数
    public Todo() {}

    public Todo(String text) {
        this.text = text;
        this.done = false;
    }

    // Getter 和 Setter
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    
    public String getText() { return text; }
    public void setText(String text) { this.text = text; }
    
    public boolean isDone() { return done; }
    public void setDone(boolean done) { this.done = done; }
}

编写 Repository(数据库操作层)

新建 TodoRepository.java

package com.example.backend;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface TodoRepository extends JpaRepository<Todo, Long> {
}

编写 Controller(API 接口)

新建 TodoController.java

package com.example.backend;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/todos")
@CrossOrigin(origins = "http://localhost:5173") // 允许前端跨域访问
public class TodoController {

    @Autowired
    private TodoRepository todoRepository;

    @GetMapping
    public List<Todo> getAllTodos() {
        return todoRepository.findAll();
    }

    @PostMapping
    public Todo createTodo(@RequestBody Todo todo) {
        return todoRepository.save(todo);
    }

    @PutMapping("/{id}")
    public Todo updateTodo(@PathVariable Long id, @RequestBody Todo todoDetails) {
        Todo todo = todoRepository.findById(id).orElseThrow();
        todo.setText(todoDetails.getText());
        todo.setDone(todoDetails.isDone());
        return todoRepository.save(todo);
    }

    @DeleteMapping("/{id}")
    public void deleteTodo(@PathVariable Long id) {
        todoRepository.deleteById(id);
    }
}

启动后端

backend 目录下运行:

./mvnw spring-boot:run  # Mac/Linux
mvnw.cmd spring-boot:run  # Windows

看到 Tomcat started on port(s): 8080 就成功了!

步骤 4:连接前后端

修改前端 App.jsx,把状态管理改成调用后端 API:

// 在文件顶部导入 useEffect
import { useState, useEffect } from 'react'

// 替换整个 App 函数
function App() {
  const [todos, setTodos] = useState([])
  const [input, setInput] = useState('')

  // 页面加载时获取数据
  useEffect(() => {
    fetch('http://localhost:8080/api/todos')
      .then(res => res.json())
      .then(data => setTodos(data))
  }, [])

  const addTodo = () => {
    if (input.trim()) {
      fetch('http://localhost:8080/api/todos', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ text: input, done: false })
      })
      .then(res => res.json())
      .then(newTodo => {
        setTodos([...todos, newTodo])
        setInput('')
      })
    }
  }

  const toggleTodo = (id) => {
    const updatedTodo = todos.find(t => t.id === id)
    updatedTodo.done = !updatedTodo.done
    fetch(`http://localhost:8080/api/todos/${id}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(updatedTodo)
    })
    .then(() => {
      setTodos(todos.map(todo =>
        todo.id === id ? updatedTodo : todo
      ))
    })
  }

  const deleteTodo = (id) => {
    fetch(`http://localhost:8080/api/todos/${id}`, {
      method: 'DELETE'
    })
    .then(() => {
      setTodos(todos.filter(todo => todo.id !== id))
    })
  }

  // ...(返回的 JSX 保持不变)
}

现在刷新前端页面,你会发现:

  • 数据保存在后端(重启前端不丢失)
  • 刷新浏览器也能看到之前添加的任务!

步骤 5:把代码推送到 GitHub

在项目根目录(my-todo-app)执行:

# 初始化 Git
git init

# 添加所有文件
git add .

# 首次提交
git commit -m "feat: 完成前后端 Todo 应用"

# 关联远程仓库(替换成你自己的地址!)
git remote add origin https://github.com/你的用户名/my-todo-app.git

# 推送到 GitHub
git push -u origin main

🔒 安全重要提示:
检查 .gitignore 文件是否包含以下内容(Vite 和 Spring Boot 会自动生成):

node_modules/
target/
.env
*.log

这些是绝对不能提交的目录/文件!


五、新手常见问题解答

Q1:为什么前端访问后端报错 “CORS error”?

原因:浏览器安全策略阻止跨域请求(前端 localhost:5173,后端 localhost:8080 算不同源)。
解决:我们在 Controller 加了 @CrossOrigin 注解,允许指定域名访问。

Q2:每次都要开两个终端?太麻烦了!

建议:用 VS Code 的 Multi-root Workspace 功能:

  1. 在根目录新建 my-todo-app.code-workspace
  2. 内容:
    {
      "folders": [
        { "path": "frontend" },
        { "path": "backend" }
      ]
    }
    
  3. 用 VS Code 打开这个文件,就能在一个窗口管理两个项目。

Q3:GitHub 提交时提示 “fatal: not a git repository”?

原因:你在子目录(如 frontend)执行了 git 命令。
解决:确保在项目根目录(包含 frontendbackend 的那层)操作。

Q4:后端启动报错 “Address already in use”?

原因:8080 端口被占用。
解决:在 backend/src/main/resources/application.properties 添加:

server.port=8081

然后前端代码里把 8080 改成 8081


六、学习建议与下一步路线

恭喜你!你已经完成了第一个全栈项目。接下来可以:

🔜 短期提升方向

  • 前端:学习 React Hooks(useEffect, useState 已接触)、组件拆分
  • 后端:了解 RESTful API 设计规范、数据库迁移(Flyway)
  • 部署:尝试把项目部署到免费平台(Vercel + Render)

🛡️ 安全意识必须养成

  • 永远不要在代码中写密码(用环境变量 .env + .gitignore
  • 对用户输入做校验(后端也要验证,不能只信前端)
  • API 加权限控制(后续学 JWT / OAuth2)

📚 推荐学习资源

  • React 官方教程(beta.react.dev)
  • Spring Boot 官方指南(spring.io/guides)
  • 我的 B 站频道:搜索“小码哥前端”,有配套视频详解

结语

我当初学的时候,也觉得 GitHub、API、跨域这些词高深莫测。但只要你动手做一遍,就会发现:所有复杂系统,都是由简单步骤组成的

今天这个项目虽然小,但它包含了现代 Web 开发的核心流程。你已经站在了正确的起点上!

记住:编程不是记住语法,而是学会“拆解问题 → 查文档 → 调试 → 解决”。遇到报错别慌,99% 的问题 Google 都有答案。

如果这篇教程对你有帮助,欢迎在评论区留言你的成果!也欢迎关注我的 B 站账号,我会持续更新更多“手把手”实战教程。

下次见!🚀

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝