第 13 节:Vue 3 + TypeScript 项目初始化
阅读时间:约 7 分钟
难度级别:实战
前置知识:Node.js、npm/yarn、Vue 基础
本节概要
通过本节学习,你将掌握:
- 使用 Vite 快速创建 Vue 3 + TypeScript 项目
- 配置项目结构和开发环境
- 集成 Naive UI 组件库
- 配置 Axios 和 HTTP 客户端
- 实现基础的路由和布局
- 项目的构建和部署配置
引言
从本节开始,我们将进入前端开发部分。Vue 3 配合 TypeScript 和 Vite,能够提供出色的开发体验和性能。本节我们将学习如何初始化项目并配置开发环境。
前端使用 Vue 3 + TypeScript + Vite 构建。本文将介绍如何从零搭建前端开发环境。
🎯 本章目标
完成后,你将拥有:
- ✅ Vue 3 + TypeScript 项目
- ✅ Vite 构建配置
- ✅ Naive UI 组件库
- ✅ Tailwind CSS 样式
- ✅ Axios HTTP 客户端
- ✅ 开发服务器运行
🚀 创建项目
Step 1: 使用 Vite 创建项目
与 AI 对话:
使用 Vite 创建一个 Vue 3 + TypeScript 项目:
- 项目名称:frontend
- 使用 TypeScript
- 使用 Vue 3
- 配置 Vite
执行命令:
# 创建项目
npm create vite@latest frontend -- --template vue-ts
# 进入项目目录
cd frontend
# 安装依赖
npm install
Step 2: 安装必要依赖
# UI 组件库
npm install naive-ui
# HTTP 客户端
npm install axios
# Markdown 渲染
npm install marked
# 代码高亮
npm install highlight.js
# 样式框架
npm install -D tailwindcss @tailwindcss/vite
# TypeScript 类型
npm install -D @types/node
最终的 package.json:
{
"name": "frontend",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc -b && vite build",
"preview": "vite preview"
},
"dependencies": {
"@tailwindcss/vite": "^4.1.18",
"axios": "^1.13.2",
"highlight.js": "^11.11.1",
"marked": "^17.0.1",
"tailwindcss": "^4.1.18",
"vue": "^3.5.24"
},
"devDependencies": {
"@types/node": "^24.10.1",
"@vitejs/plugin-vue": "^6.0.1",
"@vue/tsconfig": "^0.8.1",
"naive-ui": "^2.43.2",
"typescript": "~5.9.3",
"vite": "^7.2.4",
"vue-tsc": "^3.1.4"
}
}
⚙️ 配置 Vite
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import tailwindcss from '@tailwindcss/vite'
// Vite 配置文档: https://vite.dev/config/
export default defineConfig({
plugins: [
vue(),
tailwindcss()
],
server: {
port: 5173,
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})
配置说明:
plugins: 使用 Vue 和 Tailwind CSS 插件server.port: 开发服务器端口server.proxy: API 代理配置,将/api请求转发到后端
📝 配置 TypeScript
tsconfig.json
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}
tsconfig.app.json
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetectionKind": "force",
"noEmit": true,
"jsx": "preserve",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]
}
🎨 配置 Naive UI
src/main.ts
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
// Naive UI 组件库
import {
create,
NButton,
NCard,
NInput,
NSpace,
NLayout,
NLayoutHeader,
NLayoutContent,
NScrollbar,
NSpin,
NAvatar,
NIcon,
NEmpty,
NMessageProvider,
} from 'naive-ui'
const naive = create({
components: [
NButton,
NCard,
NInput,
NSpace,
NLayout,
NLayoutHeader,
NLayoutContent,
NScrollbar,
NSpin,
NAvatar,
NIcon,
NEmpty,
NMessageProvider,
]
})
const app = createApp(App)
app.use(naive)
app.mount('#app')
按需引入的优势:
- 减小打包体积
- 提高加载速度
- 只引入需要的组件
🌐 配置 Axios
src/api/request/axios.ts
import axios from 'axios'
const request = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000',
timeout: 60000,
})
// 请求拦截器
request.interceptors.request.use(
(config) => {
// 可以在这里添加 token
return config
},
(error) => {
return Promise.reject(error)
}
)
// 响应拦截器
request.interceptors.response.use(
(response) => {
return response
},
(error) => {
// 统一错误处理
console.error('API Error:', error)
return Promise.reject(error)
}
)
export default request
src/api/request/index.ts
import type { AxiosProgressEvent, AxiosResponse, GenericAbortSignal } from 'axios'
import request from './axios'
export interface HttpOption {
url: string
data?: any
method?: string
headers?: any
onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void
signal?: GenericAbortSignal
responseType?: 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream'
}
export interface Response<T = any> {
data: T
message: string | null
status: string
}
function http<T = any>(
{ url, data, method, headers, onDownloadProgress, signal, responseType }: HttpOption,
) {
const successHandler = (res: AxiosResponse<Response<T>>) => {
if (res.status === 200)
return res.data
return Promise.reject(res.data)
}
const failHandler = (error: Response<Error> | any) => {
return Promise.reject(error)
}
method = method || 'GET'
const params = Object.assign(typeof data === 'function' ? data() : data ?? {}, {})
if (method === 'GET')
return request.get(url, { params, signal, onDownloadProgress, responseType }).then(successHandler, failHandler)
else if (method === 'POST')
return request.post(url, params, { headers, signal, onDownloadProgress, responseType }).then(successHandler, failHandler)
else
throw new Error('不支持的请求方式')
}
export function post<T = any>(options: HttpOption): Promise<Response<T>> {
return http<T>({ ...options, method: 'POST' })
}
export function get<T = any>(options: HttpOption): Promise<Response<T>> {
return http<T>({ ...options, method: 'GET' })
}
export default post
🎨 配置样式
src/style.css
@import 'tailwindcss';
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
#app {
width: 100%;
height: 100vh;
}
src/styles/markdown.css
/* Markdown 内容样式 */
.markdown-content {
line-height: 1.6;
}
.markdown-content h1,
.markdown-content h2,
.markdown-content h3 {
margin-top: 1.5em;
margin-bottom: 0.5em;
font-weight: 600;
}
.markdown-content p {
margin: 0.8em 0;
}
.markdown-content code {
background-color: #f4f4f4;
padding: 0.2em 0.4em;
border-radius: 3px;
font-family: 'Courier New', monospace;
font-size: 0.9em;
}
.markdown-content pre {
background-color: #282c34;
padding: 1em;
border-radius: 5px;
overflow-x: auto;
margin: 1em 0;
}
.markdown-content pre code {
background-color: transparent;
padding: 0;
color: #abb2bf;
}
.markdown-content table {
border-collapse: collapse;
width: 100%;
margin: 1em 0;
}
.markdown-content th,
.markdown-content td {
border: 1px solid #ddd;
padding: 8px 12px;
text-align: left;
}
.markdown-content th {
background-color: #f8f9fa;
font-weight: 600;
}
🏃 运行项目
启动开发服务器
npm run dev
预期输出:
VITE v7.2.4 ready in 500 ms
➜ Local: http://localhost:5173/
➜ Network: http://192.168.1.100:5173/
构建生产版本
npm run build
预览生产版本
npm run preview
📁 项目结构
frontend/
├── public/ # 静态资源
│ └── vite.svg
├── src/
│ ├── api/ # API 接口
│ │ ├── request/ # Axios 封装
│ │ ├── chat.ts # 聊天 API
│ │ └── workflow.ts # Workflow API
│ ├── components/ # Vue 组件
│ │ ├── Layout.vue
│ │ ├── ChatPage.vue
│ │ └── WorkflowPage.vue
│ ├── styles/ # 样式文件
│ │ └── markdown.css
│ ├── App.vue # 根组件
│ ├── main.ts # 入口文件
│ └── style.css # 全局样式
├── index.html # HTML 模板
├── package.json # 依赖配置
├── tsconfig.json # TS 配置
├── vite.config.ts # Vite 配置
└── .env # 环境变量
🔧 环境变量
.env
# API 基础 URL
VITE_API_BASE_URL=http://localhost:8000
# 应用标题
VITE_APP_TITLE=Ask SQL
使用环境变量
// 在代码中使用
const apiUrl = import.meta.env.VITE_API_BASE_URL
const appTitle = import.meta.env.VITE_APP_TITLE
💡 Vibe Coding 要点
1. 使用脚手架
与 AI 对话:
"使用 Vite 创建 Vue 3 + TypeScript 项目,
并配置 Naive UI、Axios、Tailwind CSS"
2. 按需配置
第1步:创建基础项目
第2步:安装必要依赖
第3步:配置 Vite
第4步:配置 TypeScript
第5步:配置组件库
第6步:配置 HTTP 客户端
3. 验证配置
# 每完成一步配置,立即验证
npm run dev
# 检查是否有错误
# 访问 http://localhost:5173
本节小结
本节我们完成了前端项目的初始化:
- 项目创建:使用 Vite 创建了 Vue 3 + TypeScript 项目
- UI 组件库:集成了 Naive UI,提供丰富的组件
- HTTP 客户端:封装了 Axios,统一处理请求和响应
- 路由配置:使用 Vue Router 实现页面导航
- 布局组件:创建了基础的 Layout 组件
- 样式配置:配置了 Tailwind CSS 和全局样式
- 开发环境:配置了 Vite 和 TypeScript
现在我们有了完整的前端开发环境,可以开始实现具体功能。
思考与练习
思考题
- 为什么选择 Vite 而不是 Webpack?各有什么优劣?
- TypeScript 在 Vue 3 项目中的价值是什么?
- 如何在组件库和自定义组件之间做选择?
- 前端项目的目录结构应该如何组织?
实践练习
-
扩展项目结构:
- 添加
composables/目录用于组合式函数 - 添加
stores/目录用于状态管理 - 添加
types/目录用于类型定义
- 添加
-
优化 HTTP 客户端:
- 添加请求拦截器
- 添加响应拦截器
- 实现请求重试机制
-
主题配置:
- 配置 Naive UI 的主题
- 支持深色模式切换
- 自定义主题颜色
-
开发工具:
- 配置 ESLint 和 Prettier
- 配置 Git Hooks
- 配置 VS Code 插件
上一节:第 12 节:后端测试与调试
下一节:第 14 节:构建聊天交互界面