从零开始:手把手教你创建 Vue 3 + TypeScript 项目
本文将带你一步步创建完整的 Vue 3 项目,包含现代化的开发工具链、代码规范和最佳实践。适合前端开发者学习和参考。
前言
Vue 3 带来了 Composition API、更好的 TypeScript 支持和性能优化,是现代前端开发的较广泛的选择。本教程将从环境搭建开始,逐步创建完整的 Vue 3 项目。
环境准备
1. Node.js 环境
Vue 3 项目需要 Node.js 环境,推荐使用 LTS 版本。
Windows 系统
# 访问 Node.js 官网下载安装包
# https://nodejs.org/
# 或使用 nvm-windows 管理多个版本
# 1. 下载 nvm-windows: https://github.com/coreybutler/nvm-windows/releases
# 2. 安装并重启命令行
nvm install 20.19.0
nvm use 20.19.0
macOS 系统
# 使用 Homebrew 安装
brew install node
# 或使用 nvm 管理版本
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
source ~/.bashrc
nvm install 20.19.0
nvm use 20.19.0
验证安装
# 检查版本
node --version # 应显示 v20.19.0 或更高
npm --version # 应显示 10.x.x 或更高
2. 包管理工具
推荐使用 npm 或 pnpm,yarn 也可以。
# 全局安装 pnpm (可选)
npm install -g pnpm
# 检查版本
pnpm --version
3. IDE 配置
推荐使用 VS Code,并安装 Vue 相关插件。
必需插件
- Vue (Official) - Vue 官方插件,提供语法高亮和智能提示
- TypeScript Importer - 自动导入 TypeScript 类型
- Prettier - 代码格式化
- ESLint - 代码检查
VS Code 设置
// .vscode/settings.json
{
"typescript.preferences.importModuleSpecifier": "relative",
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.vscode-prettier",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
}
项目创建
方法一:使用 Vite 官方模板
Vite 是 Vue 官方推荐的构建工具,速度快,开发体验好。
# 创建项目
npm create vue@latest vue-course
# 进入项目目录
cd vue-course
配置选项
在创建过程中选择以下配置:
✅ TypeScript
✅ JSX
✅ Vue Router
✅ Pinia
✅ ESLint
✅ Prettier
方法二:手动创建项目
如果你喜欢自定义配置,可以手动创建。
# 创建项目目录
mkdir vue-course
cd vue-course
# 初始化 package.json
npm init -y
# 安装核心依赖
npm install vue@latest @vue/compiler-sfc@latest
npm install -D @vitejs/plugin-vue@latest vite@latest
npm install -D typescript@latest vue-tsc@latest
项目配置
1. Vite 配置
创建 vite.config.ts 文件:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': resolve(__dirname, 'src')
}
},
server: {
port: 5173,
host: true,
open: true
},
build: {
target: 'esnext',
minify: 'esbuild',
outDir: 'dist'
}
})
2. TypeScript 配置
创建 tsconfig.json:
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"composite": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
"types": ["vite/client"]
}
}
创建 tsconfig.node.json:
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["vite.config.*"],
"compilerOptions": {
"composite": true,
"types": ["node"]
}
}
创建 env.d.ts:
/// <reference types="vite/client" />
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
3. ESLint 配置
创建 eslint.config.js:
import js from '@eslint/js'
import vue from 'eslint-plugin-vue'
import typescript from '@typescript-eslint/eslint-plugin'
import typescriptParser from '@typescript-eslint/parser'
export default [
{
name: 'app/files-to-lint',
files: ['**/*.{ts,mts,tsx,vue}'],
},
{
name: 'app/files-to-ignore',
ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**'],
},
js.configs.recommended,
...vue.configs['flat/essential'],
{
name: 'app/vue-rules',
files: ['**/*.vue'],
languageOptions: {
parser: vue.parser,
parserOptions: {
parser: typescriptParser,
extraFileExtensions: ['.vue'],
sourceType: 'module',
},
},
},
{
name: 'app/typescript-rules',
files: ['**/*.{ts,mts,tsx,vue}'],
languageOptions: {
parser: typescriptParser,
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
},
},
rules: {
...typescript.configs.recommended.rules,
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/explicit-function-return-type': 'off',
},
},
]
4. Prettier 配置
创建 .prettierrc.json:
{
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100,
"endOfLine": "lf"
}
项目结构搭建
1. 基础文件结构
vue-course/
├── public/
│ ├── favicon.ico
├── src/
│ ├── assets/
│ │ ├── base.css
│ │ ├── main.css
│ │ └── logo.svg
│ ├── components/
│ │ ├── HelloWorld.vue
│ │ ├── TheWelcome.vue
│ │ ├── WelcomeItem.vue
│ │ └── icons/
│ ├── views/
│ │ ├── HomeView.vue
│ │ └── AboutView.vue
│ ├── router/
│ │ └── index.ts
│ ├── stores/
│ │ └── counter.ts
│ ├── App.vue
│ ├── main.ts
│ └── mcp-server.ts
├── .vscode/
│ └── settings.json
├── index.html
├── package.json
├── vite.config.ts
├── tsconfig.json
├── tsconfig.app.json
├── tsconfig.node.json
├── env.d.ts
├── eslint.config.ts
├── .prettierrc.json
└── README.md
2. 入口文件
src/main.ts:
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import router from './router'
import App from './App.vue'
import './assets/main.css'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')
index.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue Course</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
3. 根组件
src/App.vue:
<template>
<div id="app">
<header class="app-header">
<h1>Vue 3 项目</h1>
<nav>
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
</nav>
</header>
<main class="app-main">
<router-view />
</main>
</div>
</template>
<script setup lang="ts">
// 组件逻辑
</script>
<style scoped>
.app-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
background: #f8f9fa;
border-bottom: 1px solid #e9ecef;
}
.app-main {
padding: 2rem;
min-height: calc(100vh - 80px);
}
</style>
路由配置
1. 安装 Vue Router
npm install vue-router@4
2. 路由配置
src/router/index.ts:
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/',
name: 'Home',
component: () => import('../views/HomeView.vue'),
meta: { title: '首页' }
},
{
path: '/about',
name: 'About',
component: () => import('../views/AboutView.vue'),
meta: { title: '关于' }
}
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes
})
// 路由守卫
router.beforeEach((to, from, next) => {
document.title = `${to.meta.title} - Vue Course`
next()
})
export default router
3. 创建页面组件
src/views/HomeView.vue:
<template>
<div class="home">
<h2>欢迎使用 Vue 3</h2>
<p>当前计数: {{ count }}</p>
<button @click="increment" class="btn">增加</button>
<button @click="decrement" class="btn">减少</button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
const increment = () => count.value++
const decrement = () => count.value--
</script>
<style scoped>
.home {
text-align: center;
padding: 2rem;
}
.btn {
margin: 0 0.5rem;
padding: 0.5rem 1rem;
border: 1px solid #ccc;
border-radius: 4px;
background: white;
cursor: pointer;
}
.btn:hover {
background: #f0f0f0;
}
</style>
状态管理
1. 安装 Pinia
npm install pinia
2. 配置 Pinia
已经在 main.ts 中配置了。
3. 创建 Store
src/stores/counter.ts:
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
// 状态
const count = ref(0)
// 计算属性
const doubleCount = computed(() => count.value * 2)
// 动作
const increment = () => {
count.value++
}
const decrement = () => {
count.value--
}
const reset = () => {
count.value = 0
}
return {
count,
doubleCount,
increment,
decrement,
reset
}
})
4. 在组件中使用
<template>
<div>
<p>计数: {{ counter.count }}</p>
<p>双倍: {{ counter.doubleCount }}</p>
<button @click="counter.increment">+</button>
<button @click="counter.decrement">-</button>
</div>
</template>
<script setup lang="ts">
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
</script>
样式配置
1. 全局样式
src/assets/main.css(项目中使用的是main.css):
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
font-weight: normal;
}
a,
.green {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
}
@media (hover: hover) {
a:hover {
background-color: hsla(160, 100%, 37%, 0.2);
}
}
@media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}
#app {
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
}
}
src/assets/base.css:
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-size: 16px;
line-height: 1.5;
-webkit-text-size-adjust: 100%;
}
body {
margin: 0;
padding: 0;
color: #333;
background-color: #fff;
}
h1, h2, h3, h4, h5, h6 {
margin: 0 0 1rem 0;
font-weight: 600;
line-height: 1.2;
}
p {
margin: 0 0 1rem 0;
}
a {
color: #007acc;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
button {
font-family: inherit;
border: none;
cursor: pointer;
}
img {
max-width: 100%;
height: auto;
}
开发和构建
1. 开发服务器
# 启动开发服务器
npm run dev
# 或使用自定义端口
npm run dev -- --port 3000
2. 构建生产版本
# 构建生产版本
npm run build
# 预览构建结果
npm run preview
3. 代码检查
# 代码格式化
npm run format
# 代码检查
npm run lint
# 类型检查
npm run type-check
部署选项
1. 静态站点部署
Vercel
npm i -g vercel
vercel
Netlify
npm i -g netlify-cli
netlify deploy
常见问题
1. 依赖安装失败
# 清理缓存
npm cache clean --force
rm -rf node_modules package-lock.json
# 使用国内镜像
npm config set registry https://registry.npmmirror.com
# 重新安装
npm install
2. TypeScript 错误
确保 tsconfig.json 配置正确:
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"]
}
3. 热重载不工作
检查 Vite 配置:
export default defineConfig({
server: {
hmr: true
}
})
总结
通过本教程,你已经创建了一个完整的 Vue 3 项目,包含:
- ✅ 现代化的开发工具链
- ✅ TypeScript 支持
- ✅ 组件化架构
- ✅ 状态管理
- ✅ 路由系统
- ✅ 代码规范
- ✅ 静态站点部署
这个项目结构可以作为你开发 Vue 3 应用的起点。根据实际需求,你可以继续添加更多功能,如国际化、权限管理、数据可视化等。
资源链接
发布时间: 2026年1月 技术标签: Vue.js, TypeScript, Vite, 前端开发
希望这篇教程对你有帮助!如果有问题欢迎在评论区交流。