创建Vue3+TypeScript项目的技术文章大纲
项目初始化与环境配置
确保Node.js(建议16+)和包管理器(npm/yarn/pnpm)已安装。使用Vue CLI或Vite初始化项目,推荐Vite因其轻量和快速。
npm create vite@latest my-vue-app --template vue-ts
安装完成后检查tsconfig.json,确认strict: true以启用严格的TypeScript检查。
目录结构与核心文件说明
项目目录应包含以下关键文件:
src/main.ts:Vue应用入口文件,需明确类型声明src/App.vue:根组件,演示单文件组件(SFC)基础写法vite.config.ts:构建配置,需添加别名和TS插件支持
示例main.ts类型声明:
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.mount('#app')
组件开发与TypeScript集成
在SFC中通过<script setup lang="ts">启用组合式API。定义Props时使用defineProps并标注类型:
<script setup lang="ts">
interface Props {
title: string
count?: number
}
const props = defineProps<Props>()
</script>
状态管理与Pinia集成
安装Pinia并创建类型化的Store:
// stores/counter.ts
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
actions: {
increment() {
this.count++
}
}
})
路由配置与类型安全
使用Vue Router 4.x,在router/index.ts中定义路由时扩展RouteMeta类型:
import type { RouteRecordRaw } from 'vue-router'
declare module 'vue-router' {
interface RouteMeta {
requiresAuth?: boolean
}
}
const routes: RouteRecordRaw[] = [
{ path: '/', component: () => import('@/views/Home.vue') }
]
样式与工具类规范
推荐采用CSS Modules或Scoped CSS避免污染全局样式。配置postcss.config.js支持现代CSS特性:
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {}
}
}
构建优化与部署
通过Vite的代码分割和动态导入提升性能。配置生产环境变量:
// vite.config.ts
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue', 'pinia']
}
}
}
}
})
常见问题与调试技巧
- TS类型报错:检查
shims-vue.d.ts是否包含SFC类型声明 - HMR失效:确保Vite版本与插件兼容
- 依赖版本冲突:使用
npm ls排查嵌套依赖
单元测试与E2E方案
配置Vitest进行组件测试,示例测试文件:
import { mount } from '@vue/test-utils'
import Counter from '@/components/Counter.vue'
test('increments count', async () => {
const wrapper = mount(Counter)
await wrapper.find('button').trigger('click')
expect(wrapper.text()).toContain('Count: 1')
})
技术文章大纲:Vue3 + TypeScript 从基础到实战
安装配置与项目初始化
使用 Vue CLI 或 Vite 快速搭建 Vue3 + TypeScript 项目。
# 使用 Vue CLI
npm install -g @vue/cli
vue create vue3-ts-project
# 选择 TypeScript 和 Vue3 预设
# 使用 Vite(推荐)
npm create vite@latest vue3-ts-project --template vue-ts
cd vue3-ts-project
npm install
配置 tsconfig.json 确保 TypeScript 支持 Vue 单文件组件(SFC)。
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"exclude": ["node_modules"]
}
Vue3 核心语法与指令详解
模板语法与指令
-
插值表达式
<template> <div>{{ message }}</div> </template> <script setup lang="ts"> const message = 'Hello Vue3 + TS'; </script> -
v-bind(属性绑定)
<template> <a :href="url">Link</a> </template> <script setup lang="ts"> const url = 'https://vuejs.org'; </script> -
v-model(双向绑定)
<template> <input v-model="text" /> <p>{{ text }}</p> </template> <script setup lang="ts"> const text = ref(''); </script> -
v-if / v-else / v-show(条件渲染)
<template> <div v-if="isVisible">Visible</div> <div v-else>Hidden</div> <div v-show="isShow">Toggle Show</div> </template> <script setup lang="ts"> const isVisible = ref(true); const isShow = ref(false); </script> -
v-for(列表渲染)
<template> <ul> <li v-for="(item, index) in items" :key="index">{{ item.name }}</li> </ul> </template> <script setup lang="ts"> interface Item { name: string; } const items: Item[] = [ { name: 'Item 1' }, { name: 'Item 2' } ]; </script> -
v-on(事件绑定)
<template> <button @click="handleClick">Click Me</button> </template> <script setup lang="ts"> const handleClick = () => { alert('Button clicked!'); }; </script> -
v-html(原始 HTML 渲染)
<template> <div v-html="rawHtml"></div> </template> <script setup lang="ts"> const rawHtml = '<strong>Bold Text</strong>'; </script> -
v-once(一次性渲染)
<template> <div v-once>{{ staticMessage }}</div> </template> <script setup lang="ts"> const staticMessage = 'This will never change'; </script>
Composition API 与 TypeScript 深度集成
使用 ref 和 reactive 定义响应式数据。
<template>
<div>{{ count }}</div>
<button @click="increment">Increment</button>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const count = ref(0);
const increment = () => {
count.value++;
};
</script>
使用 computed 和 watch 处理复杂逻辑。
<template>
<div>{{ doubledCount }}</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
const count = ref(0);
const doubledCount = computed(() => count.value * 2);
</script>
组件通信与 Props 类型定义
父子组件通信
<!-- ParentComponent.vue -->
<template>
<ChildComponent :message="parentMessage" @update="handleUpdate" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const parentMessage = ref('Hello from parent');
const handleUpdate = (newMessage: string) => {
parentMessage.value = newMessage;
};
</script>
<!-- ChildComponent.vue -->
<template>
<div>{{ message }}</div>
<button @click="emitUpdate">Update Parent</button>
</template>
<script setup lang="ts">
defineProps<{
message: string;
}>();
const emit = defineEmits<{
(e: 'update', newMessage: string): void;
}>();
const emitUpdate = () => {
emit('update', 'New message from child');
};
</script>
实战案例:Todo 应用
完整实现一个 Todo 应用,涵盖增删改查功能。
<template>
<input v-model="newTodo" @keyup.enter="addTodo" />
<ul>
<li v-for="(todo, index) in todos" :key="index">
<span :class="{ done: todo.done }">{{ todo.text }}</span>
<button @click="toggleTodo(index)">Toggle</button>
<button @click="removeTodo(index)">Remove</button>
</li>
</ul>
</template>
<script setup lang="ts">
import { ref } from 'vue';
interface Todo {
text: string;
done: boolean;
}
const newTodo = ref('');
const todos = ref<Todo[]>([]);
const addTodo = () => {
if (newTodo.value.trim()) {
todos.value.push({ text: newTodo.value, done: false });
newTodo.value = '';
}
};
const toggleTodo = (index: number) => {
todos.value[index].done = !todos.value[index].done;
};
const removeTodo = (index: number) => {
todos.value.splice(index, 1);
};
</script>
<style>
.done {
text-decoration: line-through;
}
</style>
项目优化与部署
- 使用 Pinia 进行状态管理
- 配置 ESLint 和 Prettier
- 打包部署到 Vercel 或 Netlify
npm run build
通过以上内容,读者可以从零开始掌握 Vue3 + TypeScript 的核心语法、指令用法,并通过实战案例巩固知识。
941

被折叠的 条评论
为什么被折叠?



