第1章 1.1 Vue 3 介绍与开发环境
🎯 开场 3 分钟:为什么要学 Vue 3?
想象一下这个场景:你在公司做行政,老老实实用 Excel 表格记录员工的「项目进度」。
每次改个数据,要手动找格子、改内容、核对总数。如果遇到老板说「把进度>80%的项目筛选出来,按负责人分组」,你得折腾半天,眼睛都看花了。

现在问题来了——有没有一种工具,能让网页像 Excel 一样,数据变了自动更新显示,而不用你手动改来改去?
答案就是 Vue 3。它帮你把「网页显示」和「数据」绑定在一起:数据变了,网页自动跟着变。你只管专心处理数据,显示的事交给 Vue。
本文学完,你将:
- 理解 Vue 3 是什么、解决什么问题
- 搭建好开发环境,跑起你的第一个 Vue 项目
- 看到一个活生生的例子,知道 Vue 是怎么干活的
🧱 基础 25 分钟:核心概念(小白视角)
什么是 Vue 3?
说白了:Vue 3 就是一个帮你「画网页」的工具。
你可以把它理解成——网页版的「数据→画面」流水线。你把数据扔进去,Vue 自动帮你渲染成好看的网页。
举个例子:你告诉 Vue「我有一个数字叫 count,值是 0」,Vue 就画出一个显示「0」的网页。你把 count 改成 1,网页自动从「0」变成「1」,不用你手动改 HTML。
为什么要用 Vue:
- 传统写网页:改数据 → 手动找网页元素 → 改 innerHTML → 刷新看效果
- 用 Vue:改数据 → Vue 自动更新网页 → 完事
就像外卖软件:你在手机上改了个地址,骑手的 APP 自动收到新路线——不用你打电话通知。
搭建开发环境(Node.js + Vite)
Vue 3 的项目是用「Node.js」这个工具来跑的。把它理解成——运行 JavaScript 代码的发动机。
Step 1:安装 Node.js
去 https://nodejs.org ,下载「LTS(长期支持版)」,安装完打开终端,输入:
node --version
看到一串数字(比如 v20.x.x)就说明装好了。
Step 2:用 Vite 创建 Vue 项目
Vite 是 Vue 官方推荐的「项目脚手架」,说白了就是帮你自动生成项目骨架的工具。就像装修房子,你先买个「万科精装房」而不是从打地基开始。
npm create vite@latest my-vue-app -- --template vue
解释一下这行在干嘛:
- npm create vite@latest:用 npm 运行 Vite 的创建命令
- my-vue-app:你的项目名字(可以改成你喜欢的)
- -- --template vue:告诉 Vite「我要一个 Vue 项目」
创建完,进入项目目录,安装依赖:
cd my-vue-app
npm install
依赖装好之后,启动项目:
npm run dev
你会看到类似这样的输出:
VITE v5.x.x ready in 200 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help

恭喜你! 你的第一个 Vue 3 项目跑起来了。
打开浏览器,访问 http://localhost:5173/,你应该能看到一个带 Vue logo 的页面。
看看项目长什么样
用 VS Code 打开你的 my-vue-app 文件夹,你会看到这样的目录结构:
my-vue-app/
├── public/ # 放不会变的静态文件(比如网页图标)
├── src/ # 你的代码主要放这里 ★
│ ├── assets/ # 放图片、样式文件
│ ├── components/ # 放「组件」的地方(后面会讲)
│ ├── App.vue # 主组件(网页的根容器)
│ └── main.js # 入口文件(项目从这里启动)
├── index.html # 网页的「骨架」
├── package.json # 记录你用了哪些「工具包」
└── vite.config.js # Vite 的配置文件
敲黑板:src/App.vue 是你以后最常改的文件。先记住这个名字。
打开 App.vue,看看 Vue 的代码长啥样
<script setup>
import { ref } from 'vue'
const message = ref('Hello Vue!')
</script>
<template>
<div>
<h1>{{ message }}</h1>
</div>
</template>
这 3 段分别是什么意思:
| 段 | 作用 | 类比 |
|---|---|---|
<script setup> |
写 JavaScript 逻辑的地方 | 餐厅的「后厨」,决定做什么菜 |
<template> |
写 HTML 结构的地方 | 餐厅的「菜单」,决定菜长什么样 |
| (style 先忽略) | 写样式的地方 | 餐厅的「装修」,决定好不好看 |
注意这行代码:
const message = ref('Hello Vue!')
ref()是 Vue 提供的一个「包装盒」,它把普通数据包装成「响应式」数据- 响应式的意思就是:数据变了,网页自动更新
- 把
'Hello Vue!'改成'你好 Vue!',浏览器里的文字就自动变了
🔥 实战 35 分钟:3 个递进的小项目
项目 1(5 分钟):数字计数器
目标:做一个点击按钮,数字会「+1」的小工具。
把 App.vue 的内容全部替换成:
<script setup>
import { ref } from 'vue'
const count = ref(0)
function addOne() {
count.value += 1
}
</script>
<template>
<div>
<h1>当前计数:{{ count }}</h1>
<button @click="addOne">点我+1</button>
</div>
</template>
保存后,浏览器里的效果:
- 显示「当前计数:0」
- 点击按钮,数字变成 1、2、3……
解释:
- count.value 是 ref() 包装后的数据,访问值要用 .value
- @click="addOne" 意思是「点击这个按钮时,执行 addOne 函数」
项目 2(15 分钟):待办清单
目标:输入文字,按回车添加为待办事项,点击删除可划掉。
<script setup>
import { ref } from 'vue'
const todos = ref([
{ text: '买早餐', done: false },
{ text: '写周报', done: true }
])
const newTodo = ref('')
function addTodo() {
if (newTodo.value.trim() === '') return
todos.value.push({ text: newTodo.value, done: false })
newTodo.value = ''
}
function toggleDone(index) {
todos.value[index].done = !todos.value[index].done
}
function deleteTodo(index) {
todos.value.splice(index, 1)
}
</script>
<template>
<div>
<h1>我的待办清单</h1>
<input
v-model="newTodo"
@keyup.enter="addTodo"
placeholder="输入待办事项,按回车添加"
/>
<ul>
<li v-for="(todo, index) in todos" :key="index">
<span
:class="{ done: todo.done }"
@click="toggleDone(index)"
>
{{ todo.text }}
</span>
<button @click="deleteTodo(index)">删除</button>
</li>
</ul>
<p>共 {{ todos.length }} 项,已完成 {{ todos.filter(t => t.done).length }} 项</p>
</div>
</template>
<style scoped>
.done {
text-decoration: line-through;
color: gray;
}
li {
list-style: none;
margin: 8px 0;
}
</style>
效果:
- 输入「开会」,按回车,列表多了一项「开会」
- 点击「开会」,文字变灰色加删除线(表示完成)
- 点击「删除」,这一项消失
- 底部显示「共 3 项,已完成 1 项」
几个新知识点:
| 语法 | 作用 |
|---|---|
v-model="newTodo" |
把输入框和 newTodo 变量「双向绑定」,输入框打字,变量跟着变 |
v-for="..." |
循环渲染列表,就像 Python 里的 for 循环 |
:class="{ done: todo.done }" |
条件class,如果 todo.done 是 true,就加上 done 这个样式 |
项目 3(15 分钟):数据过滤器
目标:一个输入框,输入名字实时筛选下面的列表。
这个项目把「输入」和「列表显示」结合起来,模拟真实的数据处理场景。
<script setup>
import { ref, computed } from 'vue'
const employees = ref([
{ name: '张三', department: '技术部', salary: 12000 },
{ name: '李四', department: '市场部', salary: 10000 },
{ name: '王五', department: '技术部', salary: 15000 },
{ name: '赵六', department: '人事部', salary: 9000 }
])
const filterText = ref('')
const filteredEmployees = computed(() => {
if (!filterText.value) return employees.value
return employees.value.filter(e =>
e.name.includes(filterText.value) ||
e.department.includes(filterText.value)
)
})
const totalSalary = computed(() => {
return filteredEmployees.value.reduce((sum, e) => sum + e.salary, 0)
})
</script>
<template>
<div>
<h1>员工工资表</h1>
<input
v-model="filterText"
placeholder="输入姓名或部门筛选"
/>
<table border="1" style="margin-top: 16px; border-collapse: collapse;">
<thead>
<tr>
<th>姓名</th>
<th>部门</th>
<th>工资</th>
</tr>
</thead>
<tbody>
<tr v-for="emp in filteredEmployees" :key="emp.name">
<td>{{ emp.name }}</td>
<td>{{ emp.department }}</td>
<td>¥{{ emp.salary.toLocaleString() }}</td>
</tr>
</tbody>
</table>
<p>筛选后共 {{ filteredEmployees.length }} 人,合计工资 ¥{{ totalSalary.toLocaleString() }}</p>
</div>
</template>
效果:
- 输入「技术」,列表只显示张三和王五,合计工资自动更新
- 输入「15000」,没匹配结果,显示「共 0 人」
- 清空输入框,恢复显示全部
新知识点:
| 语法 | 作用 |
|---|---|
computed() |
计算属性,依赖的数据变了自动重新计算(类似 Excel 公式) |
toLocaleString() |
把数字格式化成「1,200」这种带千分位的形式 |
💪 进阶 20 分钟:常见坑 + 调试技巧
坑 1:ref 里的值不是直接读写的
// ❌ 错误:这样改 count,网页不会更新
count = 10
// ✅ 正确:要加 .value
count.value = 10
类比:ref() 像一个有「透明窗口」的保险箱,你得透过窗口(.value)才能动里面的东西。
坑 2:v-model 和输入框的类型
<!-- ❌ 如果 age 是数字,输入法打出的中文可能有问题 -->
<input v-model="age" />
<!-- ✅ 加 .number 修饰符,Vue 会自动转数字 -->
<input v-model.number="age" />
坑 3:v-for 忘了加 :key
<!-- ❌ 没加 key,Vue 会报警告,列表可能渲染出错 -->
<li v-for="todo in todos">{{ todo.text }}</li>
<!-- ✅ 加唯一的 key,Vue 知道每个元素是谁 -->
<li v-for="(todo, index) in todos" :key="index">{{ todo.text }}</li>
坑 4:模板里不要写复杂逻辑
<!-- ❌ 模板里写三元表达式嵌套,可读性差 -->
<span>{{ a ? (b ? '对' : '错') : '都不是' }}</span>
<!-- ✅ 放到 computed 里,模板只负责显示 -->
<span>{{ statusText }}</span>
原则:模板是「展示」的地方,逻辑放到 <script setup> 里。
坑 5:数组和对象的修改要小心
// ❌ 这种情况不触发响应式更新
const list = ref([1, 2, 3])
list.value[0] = 100 // ❌ 不会更新!
// ✅ 用 splice 或者整个替换
list.value.splice(0, 1, 100) // ✅ 触发更新
// 或者
list.value = [...list.value] // 触发更新(创建新数组)
调试技巧:console.log 大法
Vue 3 的 ref 对象可以直接打印看内容:
const count = ref(0)
console.log(count) // 看到的是 Ref 对象
console.log(count.value) // 看到的是 0
在 toggleDone 函数里加个 console.log,可以看到点击时数据怎么变的:
function toggleDone(index) {
console.log('点击了第', index, '项', '之前的状态:', todos.value[index].done)
todos.value[index].done = !todos.value[index].done
console.log('之后的状态:', todos.value[index].done)
}
✏️ 练习题
练习 1(1 分钟):改改计数器
- 输入:把项目 1 的
count初始值改成100 - 预期输出:页面显示「当前计数:100」,点一下按钮变成 101
- 提示:找到
ref(0),改掉那个 0 就行
练习 2(2 分钟):计数器加个「减 1」按钮
- 输入:在项目 1 基础上,加一个「点我-1」按钮
- 预期输出:两个按钮都能正常工作
- 提示:写一个
minusOne()函数,count.value -= 1
练习 3(3 分钟):待办清单加个「清空已完成」
- 输入:在项目 2 基础上,加一个按钮,点击删除所有
done: true的项 - 预期输出:点击后,已完成的事项全部消失
- 提示:用
todos.value.filter(t => !t.done)过滤出未完成的,赋值回todos.value
练习 4(3 分钟):员工表按工资排序
- 输入:在项目 3 基础上,加一个按钮,点击按工资从高到低排序
- 预期输出:点击后,表格里的顺序变了
- 提示:用
sort((a, b) => b.salary - a.salary)对filteredEmployees排序
练习 5(5 分钟):为什么没更新?
看下面这段代码,点击按钮后数字不会变,为什么?
<script setup>
const count = 0 // 没有 ref 包装!
function addOne() {
count += 1
}
</script>
<template>
<div>
<h1>{{ count }}</h1>
<button @click="addOne">点我+1</button>
</div>
</template>
- 预期输出:解释为什么网页不更新,以及怎么修
- 提示:Vue 的响应式系统需要数据被
ref()包装才能追踪变化
作业:做一个「个人开支记录器」
需求描述:做一个可以记录日常开支的小工具,输入金额和说明,保存后显示列表,底部显示总支出。
功能点:
1. 输入「金额」和「说明」,点击「添加」保存到列表
2. 显示所有开支记录,每条可以删除
3. 底部显示「总支出:¥XXX」
加分项:
1. 显示每条记录的时间(用 new Date().toLocaleString())
2. 输入验证:金额必须是正数,说明不能为空
验收标准:
- 能跑起来,npm run dev 不报错
- 添加记录后列表显示正确
- 删除记录后列表更新
- 总支出是所有记录金额之和
📚 总结 + 资源
本文学了 3 件事:
1. Vue 3 是帮你「数据→网页」自动绑定的工具
2. 用 Vite 5 分钟能搭好一个 Vue 项目
3. ref() 包装数据让它「响应式」,v-model/v-for/v-bind 是最常用的指令
延伸学习资源:
| 资源 | 链接 | 适合谁 |
|---|---|---|
| Vue 官方文档 | https://vuejs.org/tutorial/ | 喜欢看官方教程的人 |
| 《Vue 3设计与实现》 | 各大电商平台有售 | 想深入理解原理的人 |
| B站「技术浩」Vue 合集 | 搜索关键词 | 喜欢看视频学习的 |
互动钩子:你在工作中有没有遇到过「改数据要手动更新网页」的场景?当时是怎么解决的?评论区聊聊,选 3 个典型问题下期集中回答!
下期预告:下一章我们要聊一个很实际的问题——{{ message }}、v-if、v-for 这些「模板语法」到底怎么用?什么时候该用哪个?很多新手栽在这上面……

评论(0)