☰
Vue3 入门实战:2小时从零搭建响应式应用
2026/10/15 9:08:15 网站建设 项目流程

上周,一个刚转行前端的朋友问我:“Vue3 都说简单,但我看了两天官方文档,还是不知道从哪下手。有没有那种不讲历史、不讲原理,直接告诉我怎么把页面跑起来,并且能看懂每一步在干嘛的教程?”

这个问题很有意思。市面上不缺 Vue3 的教程,但很多要么从“响应式原理”开始,把新手绕晕;要么直接丢出一个庞大的后台管理系统模板,让人望而生畏。对于只想“先跑起来,再慢慢理解”的初学者来说,他们需要的不是一本百科全书,而是一张清晰的地图,上面标着:“从这里出发,走这三步,你就能到达第一个目的地。”

所以,这篇文章的目标很明确:在 2 小时内,帮你从零搭建一个可运行的 Vue3 项目,并理解其最核心的“零件”是如何组装起来的。我们不追求大而全,而是聚焦于“最小可行产品”(MVP)思维——先做出一个能动的玩具车,再研究它的发动机。文末会提供这个“玩具车”的完整源码,你可以直接拿来修改、扩展。

1. 放弃“系统学习”的执念:先动手,再解惑

很多人的学习卡点在于,总想先把所有概念都弄懂再开始写代码。这就像学开车前,非要先精通内燃机原理一样,很容易在半途耗尽热情。

对于 Vue3,尤其是速成场景,我建议你换一种思路:把 Vue3 想象成一个乐高套装。一开始,你不需要知道每个特殊零件的学名,也不需要理解塑料的分子结构。你只需要跟着说明书,把几块最大的底板拼起来,让小车能跑起来。在这个过程中,你会自然地问出:“哦,原来这个轮子是靠这根轴转动的?”——这时再去查“轴”的官方名称和原理,理解成本会低得多。

我们的“乐高说明书”将围绕这几个最核心的零件展开,它们构成了 Vue3 应用的骨架:

  1. 项目创建与环境:拿到乐高盒子(项目脚手架)。
  2. 单文件组件:认识最基础的积木块(.vue文件)。
  3. 响应式数据:让积木块之间能联动(ref,reactive)。
  4. 事件与方法:让积木块能接收你的指令(@click,methods)。
  5. 条件与列表渲染:用积木块拼出动态结构(v-if,v-for)。

遵循“先跑通,再优化”的原则,我们先快速搭建一个能显示、能点击、能变化数据的超简单应用。理解了这个流程,那些复杂的路由、状态管理、组件通信,都只是在这个骨架上添加更精巧的模块而已。

2. 第一步:10分钟搭建开发环境与第一个页面

别被“环境搭建”吓到。如今前端工具链已经非常成熟,我们借助官方的create-vue工具,几乎可以一键完成。

2.1 确保你的“工作台”就绪

在拼乐高之前,你得有张桌子。对于前端开发,这张桌子就是 Node.js 和一个代码编辑器。

  1. 安装 Node.js:去 Node.js 官网下载 LTS(长期支持)版本并安装。安装后,打开终端(Windows 用 CMD 或 PowerShell,Mac 用终端),输入node -v和npm -v,能看到版本号即表示成功。
  2. 选择一个代码编辑器:强烈推荐 Visual Studio Code,它轻量且对前端开发支持极好。下载安装即可。

2.2 一键创建 Vue3 项目

这是最关键的一步,我们通过一条命令来生成项目骨架。

打开终端,进入你打算存放项目的目录(例如cd ~/Desktop),然后执行:

npm create vue@latest

这条命令会启动一个交互式的命令行向导。你会被问到几个问题,对于初学者,我建议这样选择:

  • Project name:输入你的项目名,例如my-vue3-app。
  • Add TypeScript?No(我们先跳过,专注于 Vue 本身)
  • Add JSX Support?No
  • Add Vue Router for Single Page Application?No(第一步我们先不做多页面)
  • Add Pinia for state management?No(先不用状态管理库)
  • Add Vitest for Unit Testing?No
  • Add an End-to-End Testing Solution?» No
  • Add ESLint for code quality?Yes(建议保持,它帮你保持代码规范)
  • Add Prettier for code formatting?Yes(建议保持,自动格式化代码)

选择完成后,工具会自动创建项目文件夹并安装基础依赖。这个过程需要一点时间,取决于你的网络。

2.3 启动你的第一个应用

创建完成后,进入项目目录并启动开发服务器:

cd my-vue3-app npm install npm run dev

执行npm run dev后,终端会显示一个本地服务器地址,通常是http://localhost:5173。用浏览器打开这个地址。

恭喜!你应该能看到一个 Vue3 的默认欢迎页面。这意味着你的开发环境、项目骨架和本地服务器全部正常运行。这个页面虽然简单,但它背后已经是一个完整的、支持热重载(修改代码后页面自动刷新)的现代前端工程。

注意:如果页面没有打开,请检查终端是否有报错。最常见的问题是端口被占用,你可以按Ctrl+C停止服务器,然后修改package.json中dev脚本为vite --port 3000,再使用npm run dev启动,并通过http://localhost:3000访问。

3. 解剖核心零件:理解一个.vue文件

现在,让我们关掉默认的欢迎页面,从头开始创建我们自己的页面。打开项目,找到src/目录下的App.vue文件,清空它里面的所有内容。我们将从这里开始,像搭积木一样,一行行写出我们的应用。

一个 Vue 单文件组件(.vue)通常由三部分组成,像三明治一样:

<template> <!-- HTML 模板在这里 --> <!-- 这里写我们看到的页面结构 --> </template> <script setup> // JavaScript 逻辑在这里 // 这里定义数据、函数等 </script> <style scoped> /* CSS 样式在这里 */ /* `scoped` 表示这里的样式只作用于本组件 */ </style>

这就是 Vue 的核心哲学——关注点分离。视觉、逻辑、样式被放在同一个文件的不同区域,但又紧密关联。<script setup>是 Vue3 的组合式 API 的语法糖,它让逻辑组织变得更简单直观,我们先这样用着,知道它是“写逻辑的地方”就行。

让我们在App.vue里写下第一个组件:

<template> <div class="app"> <h1>{{ pageTitle }}</h1> <p>当前计数是:{{ count }}</p> <button @click="incrementCount">点我加1</button> </div> </template> <script setup> import { ref } from 'vue' // 1. 定义响应式数据 const pageTitle = ref('我的第一个Vue3应用') const count = ref(0) // 2. 定义方法 function incrementCount() { count.value++ // 注意,通过 .value 来修改 ref 的值 } </script> <style scoped> .app { text-align: center; padding: 2rem; } button { margin-top: 1rem; padding: 0.5rem 1rem; font-size: 1rem; cursor: pointer; } </style>

保存文件,浏览器中的页面应该会自动刷新。现在你看到了一个标题、一段显示数字的文字和一个按钮。点击按钮,数字会增加。

发生了什么?我们来拆解一下:

  1. 模板:<template>里是标准的 HTML,但多了用双花括号{{ }}包裹的pageTitle和count。这是 Vue 的模板语法,用于将 JavaScript 中定义的数据“渲染”到页面上。
  2. 逻辑:<script setup>里:
    • 我们从vue中导入了ref函数。ref是 Vue3 响应式系统的核心之一,它用来创建一个“响应式引用”。简单理解,用ref包裹的变量,当其值改变时,用到它的地方(比如模板)会自动更新。
    • const count = ref(0)创建了一个初始值为 0 的响应式变量。重点:在<script setup>中访问这个变量的值,需要使用count.value;但在<template>模板中,Vue 会自动“解包”,我们直接写count即可。
    • function incrementCount()定义了一个方法。当按钮被点击时,这个方法会执行,将count.value加 1。
  3. 样式:<style scoped>里的 CSS 只作用于当前组件,不会影响其他组件,避免了样式冲突。

这个简单的例子,已经包含了 Vue 最核心的数据驱动视图思想:数据 (count) 变化,视图(显示的数字)自动更新。你不需要手动操作 DOM 去更新文本内容。

4. 让应用活起来:掌握响应式与常用指令

刚才我们用了ref和@click。Vue 提供了一系列“指令”(Directives),它们是带有v-前缀的特殊属性,让我们能以声明的方式将数据与 DOM 绑定。

4.1 条件渲染:v-if与v-show

有时候我们需要根据条件显示或隐藏某个元素。

<template> <div> <button @click="toggleShow">切换显示</button> <p v-if="isVisible">使用v-if控制,我会被完全创建或销毁。</p> <p v-show="isVisible">使用v-show控制,我只是切换了CSS的display属性。</p> </div> </template> <script setup> import { ref } from 'vue' const isVisible = ref(true) function toggleShow() { isVisible.value = !isVisible.value } </script>
  • v-if:是“真正的”条件渲染。当条件为假时,元素及其子组件会被完全销毁和重建。切换开销较高,适用于运行时条件很少改变的场景。
  • v-show:无论条件真假,元素始终会被渲染并保留在 DOM 中,只是通过 CSSdisplay属性进行切换。切换开销较低,适用于需要频繁切换的场景。

如何选择?如果元素需要频繁切换显示/隐藏,用v-show;如果元素在大部分时间都不需要显示,或者切换不频繁,用v-if。

4.2 列表渲染:v-for

这是处理数组数据,动态生成列表的利器。

<template> <div> <ul> <li v-for="(item, index) in todoList" :key="item.id"> {{ index + 1 }}. {{ item.text }} <button @click="removeTodo(index)">删除</button> </li> </ul> <input v-model="newTodo" placeholder="输入新任务"/> <button @click="addTodo">添加</button> </div> </template> <script setup> import { ref } from 'vue' const todoList = ref([ { id: 1, text: '学习 Vue3' }, { id: 2, text: '写一个 Demo' }, ]) const newTodo = ref('') function addTodo() { if (newTodo.value.trim()) { todoList.value.push({ id: Date.now(), // 用时间戳模拟一个唯一id text: newTodo.value }) newTodo.value = '' // 清空输入框 } } function removeTodo(index) { todoList.value.splice(index, 1) } </script>
  • v-for=“(item, index) in list”:遍历数组list,item是当前项,index是索引。
  • :key=“item.id”:这是一个非常重要的属性!Vue 需要用它来跟踪每个节点的身份,从而高效地更新和重用元素。务必为每一项提供一个唯一的key,通常使用数据中的唯一 ID。
  • v-model=“newTodo”:这是“双向数据绑定”的语法糖。它相当于同时绑定了input的value属性和input事件。用户输入时,newTodo的值会自动更新;你在代码中修改newTodo.value,输入框的内容也会自动更新。

现在,你的应用已经具备了增删列表项的能力。v-model极大地简化了表单输入的处理。

4.3 处理复杂数据:reactive

ref适合处理基本类型(字符串、数字等)或需要保持引用的对象。对于复杂的对象或数组,reactive是另一个选择。

<script setup> import { reactive } from 'vue' const userInfo = reactive({ name: '张三', age: 25, address: { city: '北京' } }) function growUp() { userInfo.age++ // 直接修改属性即可,无需 .value userInfo.address.city = '上海' // 嵌套对象也是响应式的 } </script>

reactive返回的是一个响应式代理对象。与ref不同,你直接访问和修改它的属性即可,不需要.value。但请注意,reactive对基本类型无效,且整个对象被替换会失去响应性。对于初学者,一个简单的记忆方法是:单个值用ref,一组相关的属性用reactive。

5. 从玩具车到模型:组件化与代码组织

目前我们把所有代码都写在了App.vue里。当应用变大时,这会变得难以维护。Vue 的核心优势之一是组件化。我们可以把页面拆分成一个个独立、可复用的组件。

5.1 创建你的第一个子组件

在src/components/目录下,新建一个文件TodoItem.vue。

<!-- TodoItem.vue --> <template> <li class="todo-item"> <span :class="{ 'completed': todo.completed }" @click="toggleComplete"> {{ todo.text }} </span> <button @click="$emit('delete')">删除</button> </li> </template> <script setup> // 定义这个组件接收的属性 const props = defineProps({ todo: { type: Object, required: true } }) // 定义这个组件可以触发的事件 const emit = defineEmits(['delete', 'toggle']) function toggleComplete() { emit('toggle') } </script> <style scoped> .todo-item { margin: 5px 0; padding: 8px; border: 1px solid #eee; display: flex; justify-content: space-between; align-items: center; } .completed { text-decoration: line-through; color: #888; } </style>

这个组件只负责一件事:渲染一个待办事项,并处理自己的完成状态和删除事件。它通过defineProps接收父组件传来的todo数据,通过defineEmits声明自己会触发delete和toggle事件。

5.2 在父组件中使用子组件

现在,我们修改App.vue,使用这个子组件。

<!-- App.vue --> <template> <div class="app"> <h1>Todo List</h1> <ul> <TodoItem v-for="item in todoList" :key="item.id" :todo="item" @delete="deleteTodo(item.id)" @toggle="toggleTodo(item.id)" /> </ul> <!-- ... 添加任务的输入框和按钮保持不变 ... --> </div> </template> <script setup> import { ref } from 'vue' import TodoItem from './components/TodoItem.vue' // 1. 导入组件 const todoList = ref([ { id: 1, text: '学习 Vue3', completed: false }, { id: 2, text: '写一个 Demo', completed: true }, ]) const newTodo = ref('') function addTodo() { /* ... */ } function deleteTodo(id) { const index = todoList.value.findIndex(item => item.id === id) if (index > -1) { todoList.value.splice(index, 1) } } function toggleTodo(id) { const todo = todoList.value.find(item => item.id === id) if (todo) { todo.completed = !todo.completed } } </script>

关键变化:

  1. 导入:import TodoItem from './components/TodoItem.vue'
  2. 使用:在模板中,我们可以像使用 HTML 标签一样使用<TodoItem>。
  3. 传递数据:通过:todo="item"(:是v-bind:的缩写)将循环中的每一项数据传递给子组件。
  4. 监听事件:通过@delete="deleteTodo(item.id)"(@是v-on:的缩写)监听子组件触发的delete事件,并调用自己的deleteTodo方法。

通过组件化,App.vue的职责变得更清晰:管理数据列表和全局方法。而每个TodoItem负责自己的外观和行为。这就是 Vue 应用构建的基本模式——树状的组件结构。

6. 下一步:你的“玩具车”可以开往何处?

至此,你已经用不到 2 小时的时间,完成了一个具备数据响应、事件交互、条件渲染、列表渲染和基础组件化的 Vue3 应用。它虽然简单,但五脏俱全,涵盖了 Vue3 最核心的 80% 的日常使用场景。

这个“玩具车”的完整源码,你可以在这里找到:[GitHub 仓库链接](此处应放置一个真实的源码仓库链接,例如指向一个包含上述代码的 Gist 或仓库)。你可以下载它,运行npm install和npm run dev,立刻看到效果。

接下来,如果你想把这辆“玩具车”升级成“遥控车”甚至“模型赛车”,可以从以下几个方向深入:

  1. 路由:使用Vue Router。当你的应用需要多个页面(如首页、关于页、详情页)时,就需要它来管理 URL 与组件的映射关系。
  2. 状态管理:使用Pinia。当多个不直接关联的组件需要共享同一份数据(如用户登录信息)时,Pinia 提供了一个清晰、类型安全的管理方案。它比 Vuex 更简单,是 Vue3 的官方推荐。
  3. 发送网络请求:使用axios或fetch API。从后端接口获取真实数据,替换掉我们硬编码的todoList。
  4. 样式与 UI 库:探索Element Plus、Ant Design Vue或Vuetify等成熟的 UI 组件库,能极大提升开发复杂界面的效率。
  5. 构建与部署:运行npm run build,Vite 会将你的代码打包优化,生成静态文件。你可以将这些文件部署到任何静态网站托管服务(如 Vercel, Netlify, GitHub Pages)。

学习任何新技术,最快的路径永远是“在真实项目中遇到问题,然后带着问题去学习”。现在你有了一个可以运行的起点,试着去修改它:加一个“编辑”功能,改变一下样式,或者尝试把它和你熟悉的某个后端 API 连接起来。在这个过程中,你自然会去查阅 Vue3 的官方文档,而那时,文档里的每一个概念对你来说都将不再是抽象的术语,而是解决手头问题的具体工具。

记住,框架只是工具,解决问题的思路和能力才是核心。Vue3 通过其简洁的 API 和直观的组件模型,为你铺平了前端开发的道路。现在,路已经在脚下,启动你的项目,开始构建点什么吧。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询