Vue3+TypeScript项目构建实战指南

创建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 核心语法与指令详解

模板语法与指令

  1. 插值表达式

    <template>
      <div>{{ message }}</div>
    </template>
    <script setup lang="ts">
    const message = 'Hello Vue3 + TS';
    </script>
    

  2. v-bind(属性绑定)

    <template>
      <a :href="url">Link</a>
    </template>
    <script setup lang="ts">
    const url = 'https://vuejs.org';
    </script>
    

  3. v-model(双向绑定)

    <template>
      <input v-model="text" />
      <p>{{ text }}</p>
    </template>
    <script setup lang="ts">
    const text = ref('');
    </script>
    

  4. 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>
    

  5. 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>
    

  6. v-on(事件绑定)

    <template>
      <button @click="handleClick">Click Me</button>
    </template>
    <script setup lang="ts">
    const handleClick = () => {
      alert('Button clicked!');
    };
    </script>
    

  7. v-html(原始 HTML 渲染)

    <template>
      <div v-html="rawHtml"></div>
    </template>
    <script setup lang="ts">
    const rawHtml = '<strong>Bold Text</strong>';
    </script>
    

  8. v-once(一次性渲染)

    <template>
      <div v-once>{{ staticMessage }}</div>
    </template>
    <script setup lang="ts">
    const staticMessage = 'This will never change';
    </script>
    

Composition API 与 TypeScript 深度集成

使用 refreactive 定义响应式数据。

<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>

使用 computedwatch 处理复杂逻辑。

<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 的核心语法、指令用法,并通过实战案例巩固知识。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值