vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue3 TypeScript搭建项目

新手从零搭建的Vue3 + TypeScript项目

作者:咕咕一

本文介绍了如何快速搭建Vue3+TypeScript项目并实现TodoList功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、前置准备

确保电脑已安装:
Node.js(推荐 16.x 及以上,可通过 node -v 查看版本)
npm/yarn/pnpm(npm 随 Node.js 自带,推荐用 pnpm 速度更快)

二、创建 Vue3 + TS 项目

Vue 官方提供了脚手架 create-vue,是搭建 Vue3 + TS 项目的最佳方式(替代旧的 @vue/cli)。

1. 执行创建命令

打开终端(CMD/PowerShell/ 终端),运行:

# 使用 npm
npm create vue@latest
# 或使用 pnpm(推荐)
pnpm create vue@latest
# 或使用 yarn
yarn create vue@latest

注意:
node版本过低会有引擎不兼容警告,这个警告不影响项目创建,只是提示版本不满足官方推荐要求,实际大部分功能仍可正常使用。

2. 交互式配置项目(关键步骤)

执行命令后,终端会弹出一系列选项,按下面的配置选(练手项目足够用):

# 1. 输入项目名称(比如:vue3-ts-todo)
√ Project name: vue3-ts-todo
# 2. 是否使用 TypeScript?选 Yes(核心)
√ Add TypeScript? Yes
# 3. 是否使用 JSX?选 No(练手先不涉及)
√ Add JSX Support? No
# 4. 是否添加 Vue Router?选 Yes(路由是基础)
√ Add Vue Router for Single Page Application development? Yes
# 5. 是否添加 Pinia?选 Yes(状态管理,替代 Vuex)
√ Add Pinia for state management? Yes
# 6. 是否添加 Vitest?选 No(测试先不涉及)
√ Add Vitest for Unit Testing? No
# 7. 是否添加 Cypress?选 No
√ Add Cypress for both Unit and End-to-End testing? No
# 8. 是否添加 ESLint?选 Yes(代码规范)
√ Add ESLint for code quality? Yes
# 9. 是否添加 Prettier?选 No(练手简化)
√ Add Prettier for code formatting? No
# 10. 是否跳过示例代码选项?选 No(练手简化)
选 No:会保留官方示例代码,方便你参考结构,同时可以逐步替换成自己的 TodoList 功能,降低上手难度。
选 Yes:会生成完全空白的项目,需要自己从零搭建所有文件,更适合有一定经验的开发者。

3. 进入项目并安装依赖

# 进入项目目录
cd vue3-ts-todo
# 安装依赖(用 npm/pnpm/yarn 都可以)
npm install
# 或 pnpm install
# 或 yarn install

4. 启动项目

npm run dev
# 或 pnpm dev
# 或 yarn dev

启动成功后,终端会显示本地访问地址(如 http://localhost:5173/),打开浏览器访问即可看到 Vue3 初始页面。

三、熟悉项目目录结构(核心关注)

创建完成后,项目核心目录如下(重点看标星的文件):

vue3-ts-todo/
├── src/
│   ├── components/       # 组件目录(重点写 TS 组件)
│   ├── router/           # 路由配置(TS 版)
│   │   └── index.ts      # * 路由入口(TS 语法)
│   ├── stores/           # Pinia 状态管理(TS 版)
│   │   └── counter.ts    # * 示例仓库(可替换为 Todo 仓库)
│   ├── views/            # 页面组件(TS 版)
│   │   ├── AboutView.vue
│   │   └── HomeView.vue
│   ├── App.vue           # * 根组件(TS 语法)
│   ├── main.ts           # * 入口文件(TS 语法)
│   └── types/            # (手动新建)全局类型定义目录
├── package.json
├── tsconfig.json         # * TS 配置文件(核心)
└── vite.config.ts        # Vite 配置(TS 版)
# app.vue
<template>
  <!-- 模板区域 -->
  <div id="app">
    <router-view />
  </div>
</template>
 
<script setup lang="ts">
// 脚本区域
</script>
 
<style scoped>
/* 样式区域 */
}
</style>

四、实现 TodoList 练手功能(核心实战)

基于 TS 实现「添加待办、删除待办、标记完成」的核心功能,覆盖 Vue3 + TS 的核心用法:

1. 新建全局类型(src/types/todo.ts)

先定义 Todo 数据的类型(TS 核心:先定义类型,再写逻辑):

// src/types/todo.ts
// 定义单个待办项的类型
export interface Todo {
  id: number;        // 唯一标识
  content: string;   // 待办内容
  isCompleted: boolean; // 是否完成
}

// 定义 Pinia 仓库的状态类型
export interface TodoState {
  todoList: Todo[];  // 待办列表
}

2. 创建 Pinia 仓库(src/stores/todo.ts)

用 TS 约束 Pinia 的状态和方法:

// src/stores/todo.ts
import { defineStore } from 'pinia'
import type { Todo, TodoState } from '@/types/todo'

// 定义 Todo 仓库(TS 版)
export const useTodoStore = defineStore('todo', {
  // 状态:指定类型为 TodoState
  state: (): TodoState => ({
    todoList: [
      // 初始示例数据
      { id: 1, content: '学习 Vue3 + TS', isCompleted: false },
      { id: 2, content: '实现 TodoList', isCompleted: true }
    ]
  }),

  // 方法:操作待办数据(TS 约束参数/返回值)
  actions: {
    // 添加待办
    addTodo(content: string): void {
      if (!content.trim()) return
      const newTodo: Todo = {
        id: Date.now(), // 用时间戳做唯一 ID
        content,
        isCompleted: false
      }
      this.todoList.push(newTodo)
    },

    // 删除待办
    deleteTodo(id: number): void {
      this.todoList = this.todoList.filter(todo => todo.id !== id)
    },

    // 切换待办完成状态
    toggleTodo(id: number): void {
      const todo = this.todoList.find(todo => todo.id === id)
      if (todo) {
        todo.isCompleted = !todo.isCompleted
      }
    }
  }
})

3. 编写 TodoList 组件(src/components/TodoList.vue)

这是核心组件,覆盖 Vue3 + TS 的核心语法(

<template>
  <div class="todo-container">
    <h2>Vue3 + TS 待办事项</h2>
    
    <!-- 添加待办 -->
    <div class="todo-add">
      <input
        v-model="inputValue"
        placeholder="请输入待办内容"
        @keyup.enter="handleAddTodo"
        class="todo-input"
      />
      <button @click="handleAddTodo" class="add-btn">添加</button>
    </div>

    <!-- 待办列表 -->
    <ul class="todo-list">
      <li 
        v-for="todo in todoStore.todoList" 
        :key="todo.id"
        :class="{ completed: todo.isCompleted }"
      >
        <input
          type="checkbox"
          :checked="todo.isCompleted"
          @change="todoStore.toggleTodo(todo.id)"
        />
        <span>{{ todo.content }}</span>
        <button @click="todoStore.deleteTodo(todo.id)" class="del-btn">删除</button>
      </li>
    </ul>

    <!-- 空列表提示 -->
    <div v-if="todoStore.todoList.length === 0" class="empty-tip">
      暂无待办事项,添加一个吧~
    </div>
  </div>
</template>

<script setup lang="ts">
// 1. 导入 Pinia 仓库
import { useTodoStore } from '@/stores/todo'
// 2. 导入 Vue 响应式 API(TS 自动推导类型)
import { ref } from 'vue'

// 3. 初始化仓库
const todoStore = useTodoStore()

// 4. 响应式数据(TS 注解:字符串类型)
const inputValue = ref<string>('')

// 5. 方法(TS 约束:无参数、无返回值)
const handleAddTodo = (): void => {
  todoStore.addTodo(inputValue.value)
  // 清空输入框
  inputValue.value = ''
}
</script>

<style scoped>
.todo-container {
  width: 500px;
  margin: 50px auto;
  padding: 20px;
  border: 1px solid #eee;
  border-radius: 8px;
}
.todo-add {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}
.todo-input {
  flex: 1;
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
}
.add-btn {
  padding: 8px 16px;
  background: #42b983;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
.todo-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.todo-list li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px;
  border-bottom: 1px solid #eee;
}
.todo-list li.completed span {
  text-decoration: line-through;
  color: #999;
}
.del-btn {
  margin-left: auto;
  padding: 4px 8px;
  background: #ff4444;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 12px;
}
.empty-tip {
  text-align: center;
  color: #999;
  padding: 20px;
}
</style>

4. 修改首页组件(src/views/HomeView.vue)

把 TodoList 组件引入首页,替换默认内容:

<template>
  <main>
    <TodoList />
  </main>
</template>

<script setup lang="ts">
import TodoList from '@/components/TodoList.vue'
</script>

<style scoped>
main {
  padding: 1rem;
}
</style>

5. 简化路由(可选)

打开 src/router/index.ts,确保路由配置正确(TS 版):
typescript

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

// TS 约束路由类型(Vue Router 内置)
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: HomeView
    },
    {
      path: '/about',
      name: 'about',
      // 懒加载组件(TS 自动识别类型)
      component: () => import('../views/AboutView.vue')
    }
  ]
})

export default router

五、运行项目,查看效果

重新启动项目(如果之前没关就不用):

npm run dev

访问 http://localhost:5173/,你会看到:
带输入框的 TodoList 界面
可输入内容添加待办
勾选复选框标记完成 / 未完成
点击删除按钮移除待办
空列表时显示提示文字

六、核心 TS 知识点回顾(练手重点)

这个项目中你用到的 Vue3 + TS 核心语法:
<script setup lang="ts">:Vue3 组合式 API + TS 的核心写法
类型注解:ref(‘’)、(): void 等,约束响应式数据 / 方法的类型
接口(interface):定义 Todo 数据结构,统一数据类型
Pinia + TS:约束仓库的状态和方法,避免传参 / 返回值错误
路由 TS 类型:Vue Router 内置类型,自动约束路由配置

七、拓展练习(进阶)

如果想进一步练习,可以给项目加功能:
给 Todo 加「编辑」功能(约束编辑输入的类型)
按「完成 / 未完成」筛选 Todo(TS 约束筛选条件)
本地存储 Todo 数据(用 localStorage,TS 约束存储 / 读取的数据类型)

总结

本次搭建的核心关键点:
项目搭建:用官方 create-vue 选择 TypeScript 选项,快速生成规范的 Vue3 + TS 项目;
TS 核心:先定义接口(interface)约束数据结构,再写逻辑,养成「先类型后逻辑」的习惯;
Vue3 结合<script setup lang="ts"> 中用 ref/reactive 时添加类型注解,Pinia 仓库用 TS 约束状态和方法。

到此这篇关于新手从零搭建的Vue3 + TypeScript项目的文章就介绍到这了,更多相关Vue3 TypeScript搭建项目内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文