深入 Vue 3 响应式开发:从零构建一个功能完整的 Todo 应用(超详细实战解析)
在当今前端开发领域,Vue.js 凭借其简洁的语法、强大的响应式系统和高效的开发体验,赢得了全球数百万开发者的青睐。尤其自 Vue 3 引入 Composition API 后,代码组织更灵活、逻辑复用更便捷,使得复杂应用的开发变得前所未有的清晰与高效。
本文将以一个完整、可运行的 Vue 3 Todo 任务清单应用为案例,带你从零开始,逐行、逐概念、深入底层地理解 Vue 的核心思想——“数据驱动视图”。我们将不仅解释“怎么写”,更要讲清楚“为什么这样写”、“背后发生了什么”以及“它比传统方式好在哪里”。无论你是刚入门的新手,还是希望巩固 Vue 原理的进阶者,这篇文章都将为你提供一次沉浸式的深度学习体验。
一、项目概览:我们要构建什么?
这个 Todo 应用具备以下功能:
- 动态标题:顶部显示标题(如“Todos任务清单”),用户可直接编辑
- 任务添加:在输入框中输入内容,按下回车键即可新增一条任务
- 任务状态管理:每条任务左侧有复选框,点击可标记为“已完成”
- 视觉反馈:已完成的任务文字变为灰色并带有删除线
- 智能计数:底部实时显示“未完成任务数 / 总任务数”
- 全选/全不选:一个复选框即可一键切换所有任务的状态
- 空状态提示:当任务列表为空时,显示“暂无计划”
这些功能看似简单,但在传统 JavaScript 中,需要大量繁琐的 DOM 操作、事件监听和状态同步。而在 Vue 中,你只需关注数据本身,框架会自动处理所有 UI 更新。
二、核心哲学:Vue 的“数据驱动”思想
传统开发 vs Vue 开发
在没有框架的时代,开发者必须手动操作 DOM:
// 找到元素
const titleEl = document.getElementById('title');
// 修改内容
titleEl.innerText = newTitle;
// 监听输入
input.addEventListener('input', (e) => {
// 手动同步数据
currentTitle = e.target.value;
// 手动更新其他依赖
updateCount();
});
这种方式存在三大痛点:
- 代码冗余:每个交互都需要重复的查找 + 修改
- 状态不同步:容易遗漏更新,导致界面与数据不一致
- 难以维护:逻辑分散,修改一处可能影响多处
而 Vue 的做法截然不同:
“你描述世界应该是什么状态,我负责让页面变成那样。”
你不再写“如何改页面”,而是写“数据现在是什么”。例如:
- 想让标题变?→ 改
title的值 - 想加新任务?→ 往
todos数组里 push 一个对象 - 想标记完成?→ 设
todo.done = true
Vue 会自动追踪这些变化,并精准更新所有受影响的 UI 部分。正如你在注释中所写:“vue focus 数据业务,修改这个数据,余下的 dom 更新 vue 替我们做了。”——这正是 Vue 的灵魂所在。
三、模板层详解:声明式 UI 的力量
1. 数据绑定:{{ title }}
<h2>{{ title }}</h2>
这是 Vue 最基础的插值语法。它告诉 Vue:“在这里显示 title 的当前值”。当 title 是一个响应式变量(通过 ref 创建)时,任何对其 .value 的修改都会触发 <h2> 内容的自动更新。无需 innerHTML,无需 innerText,一切自动发生。
2. 双向绑定与事件处理
<input type="text" v-model="title" @keydown.enter="addTodo">
-
v-model="title"是 Vue 的双向绑定指令,等价于::value="title" @input="title = $event.target.value"它同时完成了“数据 → 视图”和“视图 → 数据”的同步。
-
@keydown.enter="addTodo"中:@是v-on:的缩写,用于监听 DOM 事件.enter是事件修饰符,表示“仅在按下回车键时触发”addTodo是定义在<script setup>中的函数
这种写法彻底告别了 addEventListener,让事件处理变得声明式且集中。
3. 条件渲染与列表循环
<ul v-if="todos.length">
<li v-for="todo in todos" :key="todo.id"> ... </li>
</ul>
<div v-else>暂无计划</div>
-
v-if/v-else实现条件渲染:根据todos.length是否大于 0 决定显示列表还是提示信息。 -
v-for是列表渲染指令,遍历todos数组,为每个元素生成一个<li>。 -
:key="todo.id"至关重要:key是 Vue 识别每个节点的“唯一身份证”- 当列表发生变化(如删除中间项),Vue 能通过
key精准判断哪些节点需要移动、更新或销毁 - 若不使用
key或使用数组索引,可能导致状态错乱或性能下降
4. 动态样式与状态联动
<input type="checkbox" v-model="todo.done">
<span :class="{'done': todo.done}">{{ todo.title }}</span>
-
复选框通过
v-model与todo.done双向绑定,点击即改变数据状态 -
:class是v-bind:class的缩写,用于动态绑定 CSS 类{'done': todo.done}表示:当todo.done为true时,添加done类
-
在
<style>中:.done { color: gray; text-decoration: line-through; }浏览器自动应用样式,实现视觉反馈
整个过程无需一行 JavaScript 操作样式,完全由数据驱动。
5. 底部状态栏:计算属性的完美舞台
全选 <input type="checkbox" v-model="allDone">
{{ active }} / {{ todos.length }}
这里引入了两个关键概念:
allDone:一个可写的计算属性,实现全选逻辑active:一个只读计算属性,表示未完成任务数量
它们共同展示了 Vue 如何将复杂逻辑封装为简洁的模板表达式。
四、逻辑层剖析:Composition API 的优雅实践
1. 响应式数据:ref
const title = ref("Todos任务清单");
const todos = ref([ ... ]);
ref()创建一个响应式引用对象,其值通过.value访问- Vue 3 使用
Proxy对ref进行拦截,实现依赖收集与派发更新 - 当模板中使用
{{ title }}时,Vue 自动建立依赖关系:一旦title.value改变,相关 DOM 就会更新
2. 计算属性:computed
只读计算属性:active
const active = computed(() => {
return todos.value.filter(todo => !todo.done).length;
});
-
computed返回一个记忆化(memoized)的响应式值 -
优势:
- 性能优化:只要
todos未变,多次访问active不会重复执行过滤操作 - 自动响应:当
todos中任一任务的done状态改变,active自动重新计算
- 性能优化:只要
-
在模板中直接使用
{{ active }},Vue 会自动解包.value
可写计算属性:allDone
const allDone = computed({
get() {
return todos.value.length > 0 && todos.value.every(todo => todo.done);
},
set(val) {
todos.value.forEach(todo => todo.done = val);
}
});
这是 Vue 中实现“全选”功能的最佳实践:
- get:判断是否所有任务都已完成(注意处理空列表情况)
- set:当用户点击“全选”复选框,将所有任务的
done设为val - 通过
v-model="allDone",一个复选框就实现了双向控制,代码极其简洁且健壮
3. 方法:addTodo
const addTodo = () => {
if (!title.value.trim()) return;
todos.value.push({
id: Date.now(),
title: title.value,
done: false
});
title.value = '';
};
- 核心思想:“focus 数据业务”——只操作数据,不关心 UI
- 推入的是结构一致的对象(含
id,title,done),确保模板中{{ todo.title }}不会报错 - 清空输入框,准备下一次输入
整个过程没有创建任何 DOM 元素,没有调用任何 appendChild,一切由 Vue 的响应式系统和虚拟 DOM 机制自动处理。
五、为什么 Vue 开发如此高效?
- 声明式编程
你描述“UI 应该是什么样子”,而不是“如何一步步操作 DOM”,大幅降低认知负担。 - 响应式系统
数据变化 → 自动更新视图,避免手动同步带来的 bug。 - 组合式 API
逻辑按功能组织(如addTodo,allDone),易于测试、复用和维护。 - 指令系统
v-if、v-for、v-model等封装了常见模式,语义清晰,减少样板代码。 - 计算属性
自动缓存 + 响应式,性能与开发体验兼得。
六、结语:从“操作 DOM”到“管理状态”
这段代码,不仅是一个功能完整的 Todo 应用,更是一份对 Vue 核心思想的完美诠释。你准确地抓住了现代前端开发的本质转变:
从前,我们操作 DOM;现在,我们管理状态。
掌握这一思想,你不仅能写出更健壮的 Vue 应用,也能更好地理解 React、Svelte 等其他响应式框架的设计哲学。继续深入 Vue 的世界吧——响应式、组件化、组合式 API……每一层都藏着让开发变得更简单、更快乐的魔法。
愿你在编程之路上,越走越远,越写越爽!🌟