
Vue 3 快速入门从零搭建前后端 CRUD 应用本文面向想要快速上手 Vue 3 并打通前后端的开发者。通过一个完整示例涵盖 Vue 3 安装、项目创建、组件编写以及通过 Axios 调用 FastAPI SQLite 后端接口实现对数据库的增删改查。技术栈Vue 3 · Vite · FastAPI · SQLite · Axios · Composition API目录什么是 Vue 3安装与环境准备创建 Vue 3 项目Vue 单文件组件基础后端FastAPI SQLiteFastAPI CRUD 完整代码Vue 调用后端接口完整 CRUD 页面示例下一步建议1. 什么是 Vue 3Vue 3 是 Vue.js 的最新主要版本相比 Vue 2 有三项关键提升维度Vue 2Vue 3API 风格Options API选项式Composition API组合式script setup状态管理VuexPinia更轻量、更好 TypeScript 支持渲染性能旧 Virtual DOM重写后的 Virtual DOM渲染速度大幅提升Vue 3 的核心优势渐进式从简单页面到复杂应用按需引入无需全栈重构Composition API逻辑复用性更强、代码组织更清晰、天然支持 TypeScript性能Virtual DOM 重写配合编译器优化运行速度和打包体积均显著改善生态成熟Vue Router 4、Pinia、Vite 组成完整工具链 Vue 2 于 2023 年底正式停止维护新项目请直接使用 Vue 3。2. 安装与环境准备2.1 前提条件确保已安装Node.js ≥ 16.0node-v# v20.x.x 或更高版本均可npm-v# npm 8.x没有安装前往 nodejs.org 下载 LTS 版本。2.2 两种安装方式方式一CDN 快速体验无需构建适合写 Demo、验证想法或者在旧项目中局部引入 Vue 3。创建一个index.html即可!DOCTYPEhtmlhtmllangzhheadmetacharsetUTF-8titleVue 3 CDN Demo/title/headbodydividapph1{{ message }}/h1buttonclickcount点击次数{{ count }}/button/divscripttypemoduleimport{createApp,ref}fromhttps://unpkg.com/vue3/dist/vue.esm-browser.jscreateApp({setup(){constmessageref(Hello, Vue 3!)constcountref(0)return{message,count}}}).mount(#app)/script/body/html直接在浏览器打开即可运行无需任何构建工具。方式二npm Vite推荐工程化方式CDN 适合尝鲜但真实项目需要工程化能力热更新、模块打包、TypeScript 支持等。Vite是 Vue 官方推荐的构建工具由 Vue 的作者尤雨溪主导开发相比 Vue CLI 有显著的速度优势npm create vitelatest my-app -- --template vue cd my-app npm install npm run dev启动后访问http://localhost:5173/即可看到默认项目页面。3. 创建 Vue 3 项目3.1 完整步骤# 1. 创建项目交互式会让你选 Vue 或 Vue-tsnpmcreate vitelatest my-app ----templatevue# 2. 进入目录cdmy-app# 3. 安装依赖npminstall# 4. 安装 Axios用于调用后端 APInpminstallaxios# 5. 启动开发服务器npmrun dev# 输出Local: http://localhost:5173/# Network: http://192.168.x.x:5173/3.2 项目结构一览my-app/ ├── public/ # 静态资源原样复制到构建产物 ├── src/ │ ├── assets/ # 样式、图片等资源 │ ├── components/ # ✅ 放你的 .vue 组件 │ ├── App.vue # ✅ 根组件入口 │ └── main.js # ✅ 应用入口文件 ├── index.html # HTML 模板 ├── vite.config.js # Vite 配置 └── package.json3.3 安装 Python 后端依赖后端使用 FastAPI还需要安装 Python 依赖# 建议用虚拟环境python3-mvenv venvsourcevenv/bin/activate# macOS/Linux# venv\Scripts\activate # Windowspipinstallfastapi uvicorn4. Vue 单文件组件基础Vue 单文件组件.vue后缀将template模板、script逻辑、style样式三部分合为一体是 Vue 项目的标准写法。4.1 一个最小示例!-- src/App.vue -- template div classcard h1{{ title }}/h1 p{{ message }}/p button clickcount点击次数{{ count }}/button /div /template script setup import { ref } from vue // 响应式状态Composition API 写法 const title ref(Vue3 入门) const message ref(你好世界) const count ref(0) /script style scoped .card { padding: 1.5rem; border-radius: 12px; background: #1e293b; color: #f1f5f9; max-width: 400px; margin: 2rem auto; } h1 { color: #42b883; } button { background: #42b883; color: #fff; border: none; padding: 0.5rem 1rem; border-radius: 6px; cursor: pointer; font-size: 1rem; } /style4.2 关键语法解释语法说明{{ title }}双大括号插值渲染变量值clickcountclick是v-on:click的简写绑定事件ref()创建响应式变量修改.value自动更新视图style scoped样式仅对当前组件生效避免污染全局4.3script setup是什么script setup是 Vue 3.2 引入的语法糖与以下写法完全等价// 编译后等价于import{ref}fromvueexportdefault{setup(){consttitleref(Vue3 入门)constmessageref(你好世界)constcountref(0)return{title,message,count}}}使用script setup代码更简洁是 Vue 3 的推荐写法。5. 后端FastAPI SQLite5.1 为什么选 FastAPI性能接近 Node.js 和 Go可处理高并发请求自动文档运行后访问http://127.0.0.1:8000/docs自动生成可交互的 Swagger UI类型安全原生支持 Python 类型提示配合 Pydantic 自动校验请求数据异步支持使用async def轻松处理 IO 密集型任务上手极快Flask 式的简洁语法Django 式的功能完整5.2 SQLite零配置的嵌入式数据库SQLite 无须独立服务进程数据存储在一个.db文件中非常适合中小型应用和本地开发importsqlite3# 建立连接文件不存在会自动创建connsqlite3.connect(data.db)cursorconn.cursor()# 执行 SQLcursor.execute( CREATE TABLE IF NOT EXISTS items ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, description TEXT ) )conn.commit()conn.close()5.3 最小化后端代码创建后端文件backend/main.pyfromfastapiimportFastAPIfromfastapi.middleware.corsimportCORSMiddlewareimportsqlite3 appFastAPI(titleVue3 CRUD API)DBbackend/data.db# SQLite 数据库文件# ── CORS 配置允许 Vue 前端跨域访问 ──app.add_middleware(CORSMiddleware,allow_origins[http://localhost:5173],# Vite 默认端口allow_credentialsTrue,allow_methods[*],allow_headers[*],)defget_conn():获取数据库连接的辅助函数returnsqlite3.connect(DB)# ── 启动时初始化数据库 ──app.on_event(startup)definit_db():withget_conn()asconn:conn.execute( CREATE TABLE IF NOT EXISTS items ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, description TEXT ) )conn.commit()print(✅ 数据库初始化完成)启动后端cdbackend uvicorn main:app--reload--port8000# 输出# INFO: Uvicorn running on http://127.0.0.1:8000# ✅ 数据库初始化完成访问http://127.0.0.1:8000/docs可以看到自动生成的交互式 API 文档。6. FastAPI CRUD 完整代码下面是与数据库items表交互的完整 CRUD 接口。放在backend/main.py的init_db()之后frompydanticimportBaseModel# ── Pydantic 模型定义请求体结构并自动校验类型 ──classItem(BaseModel):name:strdescription:str|NoneNone# 可选字段# ══════════════════════════════════════════════# 查询全部 GET /items# ══════════════════════════════════════════════app.get(/items)defget_items():withget_conn()asconn:rowsconn.execute(SELECT * FROM items).fetchall()return[{id:r[0],name:r[1],description:r[2]}forrinrows]# ══════════════════════════════════════════════# 查询单条 GET /items/{id}# ══════════════════════════════════════════════app.get(/items/{id})defget_item(id:int):fromfastapiimportHTTPExceptionwithget_conn()asconn:rconn.execute(SELECT * FROM items WHERE id?,[id]).fetchone()ifnotr:raiseHTTPException(status_code404,detailItem not found)return{id:r[0],name:r[1],description:r[2]}# ══════════════════════════════════════════════# ➕ 新增 POST /items# ══════════════════════════════════════════════app.post(/items)defcreate_item(item:Item):withget_conn()asconn:curconn.execute(INSERT INTO items (name, description) VALUES (?, ?),[item.name,item.description])conn.commit()return{id:cur.lastrowid,**item.model_dump()}# ══════════════════════════════════════════════# ✏️ 修改 PUT /items/{id}# ══════════════════════════════════════════════app.put(/items/{id})defupdate_item(id:int,item:Item):withget_conn()asconn:conn.execute(UPDATE items SET name?, description? WHERE id?,[item.name,item.description,id])conn.commit()return{id:id,**item.model_dump()}# ══════════════════════════════════════════════# ️ 删除 DELETE /items/{id}# ══════════════════════════════════════════════app.delete(/items/{id})defdelete_item(id:int):withget_conn()asconn:conn.execute(DELETE FROM items WHERE id?,[id])conn.commit()return{ok:True,deleted:id}路由方法对照表方法路径作用Postman / curl 示例GET/items查询全部记录curl http://localhost:8000/itemsGET/items/{id}查询单条记录curl http://localhost:8000/items/1POST/items新增一条记录curl -X POST http://localhost:8000/items -H Content-Type: application/json -d {name:测试,description:描述}PUT/items/{id}修改指定记录curl -X PUT http://localhost:8000/items/1 -H Content-Type: application/json -d {name:修改后,description:新描述}DELETE/items/{id}删除指定记录curl -X DELETE http://localhost:8000/items/17. Vue 调用后端接口7.1 封装 Axios API 模块为了代码整洁把所有 API 调用封装到一个文件src/api/items.js// src/api/items.jsimportaxiosfromaxios// 创建 Axios 实例配置 baseURLconstapiaxios.create({baseURL:http://localhost:8000,// FastAPI 后端地址headers:{Content-Type:application/json}})// ── GET /items查询全部 ──exportconstgetItems()api.get(/items)// ── GET /items/{id}查询单条 ──exportconstgetItem(id)api.get(/items/${id})// ── POST /items新增 ──exportconstcreateItem(data)api.post(/items,data)// ── PUT /items/{id}修改 ──exportconstupdateItem(id,data)api.put(/items/${id},data)// ── DELETE /items/{id}删除 ──exportconstdeleteItem(id)api.delete(/items/${id})7.2 在组件中调用在 Vue 组件中使用onMounted钩子在页面加载时获取数据!-- src/App.vue -- script setup import { ref, onMounted } from vue import { getItems, createItem, updateItem, deleteItem } from ./api/items const items ref([]) // 列表数据 const form ref({ // 表单数据 name: , description: }) const editingId ref(null) // 当前编辑中的 IDnull 表示新增模式 // ── 页面加载时获取数据 ── onMounted(async () { try { const { data } await getItems() items.value data } catch (err) { console.error(加载失败, err) } }) // ── 新增 ── const handleCreate async () { const { data } await createItem(form.value) items.value.push(data) form.value { name: , description: } } // ── 点击编辑 ── const handleEdit (item) { editingId.value item.id form.value { name: item.name, description: item.description } } // ── 更新 ── const handleUpdate async () { const { data } await updateItem(editingId.value, form.value) const idx items.value.findIndex(i i.id editingId.value) if (idx ! -1) items.value[idx] data // 更新列表中的对应项 editingId.value null form.value { name: , description: } } // ── 删除 ── const handleDelete async (id) { await deleteItem(id) items.value items.value.filter(i i.id ! id) // 从列表中移除 } /script8. 完整 CRUD 页面示例下面是一个完整的列表管理页面包含输入表单和表格代码可直接复制使用。创建src/components/ItemList.vue!-- src/components/ItemList.vue -- script setup import { ref, onMounted } from vue import { getItems, createItem, updateItem, deleteItem } from ../api/items const items ref([]) const form ref({ name: , description: }) const editingId ref(null) // ── 加载列表 ── onMounted(async () { const { data } await getItems() items.value data }) // ── 新增 ── const handleCreate async () { if (!form.value.name.trim()) return const { data } await createItem(form.value) items.value.push(data) form.value { name: , description: } } // ── 编辑 ── const handleEdit (item) { editingId.value item.id form.value { name: item.name, description: item.description } } // ── 更新 ── const handleUpdate async () { const { data } await updateItem(editingId.value, form.value) const idx items.value.findIndex(i i.id editingId.value) if (idx ! -1) items.value[idx] data editingId.value null form.value { name: , description: } } // ── 删除 ── const handleDelete async (id) { if (!confirm(确认删除)) return await deleteItem(id) items.value items.value.filter(i i.id ! id) } // ── 取消编辑 ── const cancelEdit () { editingId.value null form.value { name: , description: } } /script template div classcrud-container h2 项目列表管理/h2 !-- 输入表单 -- div classform-section input v-modelform.name placeholder输入名称... keyup.entereditingId ? handleUpdate() : handleCreate() / input v-modelform.description placeholder输入描述可选... keyup.entereditingId ? handleUpdate() : handleCreate() / button v-if!editingId clickhandleCreate classbtn-add ➕ 新增 /button template v-else button clickhandleUpdate classbtn-update✓ 更新/button button clickcancelEdit classbtn-cancel✕ 取消/button /template /div !-- 列表表格 -- table classitems-table thead tr thID/th th名称/th th描述/th th操作/th /tr /thead tbody tr v-ifitems.length 0 td colspan4 classempty-row暂无数据/td /tr tr v-foritem in items :keyitem.id td{{ item.id }}/td td{{ item.name }}/td td{{ item.description || — }}/td td button clickhandleEdit(item) classbtn-edit✏ 编辑/button button clickhandleDelete(item.id) classbtn-del 删除/button /td /tr /tbody /table /div /template style scoped .crud-container { max-width: 800px; margin: 2rem auto; padding: 0 1rem; font-family: system-ui, sans-serif; } h2 { color: #42b883; margin-bottom: 1rem; } .form-section { display: flex; gap: 0.5rem; margin-bottom: 1.5rem; flex-wrap: wrap; } input { padding: 0.5rem 0.75rem; border: 1px solid #334155; border-radius: 6px; background: #1e293b; color: #f1f5f9; font-size: 0.95rem; flex: 1; min-width: 160px; } input::placeholder { color: #64748b; } input:focus { outline: 2px solid #42b883; border-color: transparent; } button { padding: 0.5rem 1rem; border: none; border-radius: 6px; cursor: pointer; font-size: 0.9rem; font-weight: 500; transition: opacity 0.2s; } button:hover { opacity: 0.85; } .btn-add { background: #22c55e; color: #fff; } .btn-update { background: #3b82f6; color: #fff; } .btn-cancel { background: #475569; color: #fff; } .btn-edit { background: #f59e0b; color: #fff; margin-right: 0.4rem; } .btn-del { background: #ef4444; color: #fff; } .items-table { width: 100%; border-collapse: collapse; background: #1e293b; border-radius: 8px; overflow: hidden; } th { background: #0f172a; color: #94a3b8; font-weight: 600; text-align: left; padding: 0.75rem 1rem; font-size: 0.85rem; letter-spacing: 0.05em; } td { padding: 0.75rem 1rem; border-top: 1px solid #334155; color: #f1f5f9; font-size: 0.9rem; } tr:hover td { background: #1e293b; } .empty-row { text-align: center; color: #64748b; padding: 2rem; } /style然后在App.vue中引入使用!-- src/App.vue -- script setup import ItemList from ./components/ItemList.vue /script template main ItemList / /main /template9. 下一步建议掌握以上内容后可以沿着以下方向继续深入路由与页面导航安装 Vue Router实现多页面切换npminstallvue-router状态管理使用 Pinia 在组件间共享复杂状态npminstallpinia后端进阶用SQLAlchemy或PeeweeORM 替代手写 SQL添加JWT 认证保护接口使用PostgreSQL替代 SQLite 支持生产部署部署上线前端运行npm run build用 Nginx 做反向代理后端用Docker容器化或部署到 Railway / Render / 阿里云 ECS学习资源Vue 3 官方文档中文FastAPI 官方文档英文Vite 官方文档Vue Router 4 文档Pinia 文档完整项目结构project/ ├── backend/ │ ├── main.py # FastAPI 后端CRUD 接口 │ └── data.db # SQLite 数据库自动生成 └── my-app/ # Vue 3 前端 ├── src/ │ ├── api/ │ │ └── items.js # Axios API 封装 │ ├── components/ │ │ └── ItemList.vue # 完整 CRUD 页面 │ └── App.vue └── vite.config.js启动方式# 终端 1后端cdbackenduvicorn main:app--reload--port8000# 终端 2前端cdmy-appnpmrun dev打开http://localhost:5173即可看到完整的增删改查应用。祝编码愉快