在前端开发中,任务清单(Todos)是一个经典练习项目。它虽功能简单,却能完整体现数据驱动、状态管理与用户交互的核心思想。若用传统 DOM 操作实现,代码往往冗长且难以维护;而借助 Vue 3 的组合式 API 与响应式系统,我们只需关注"数据如何变化",界面便会自动同步更新。这种声明式开发范式,不仅提升了开发效率,也让代码逻辑更清晰、更易测试。
从命令式到声明式:思维的转变
传统 JavaScript 开发通常采用命令式编程:先获取 DOM 元素,再监听事件,最后手动修改内容。
ini
const app = document.getElementById('app');
const input = document.getElementById('todo-input');
input.addEventListener('change', (e) => {
app.innerHTML = e.target.value.trim();
});
这种方式直接操作渲染引擎,每一步都需精确控制。一旦逻辑复杂(如增删改查、筛选、全选),代码会迅速膨胀,且容易因状态不一致导致 bug。
而 Vue 的核心理念是响应式数据驱动:你不再操作 DOM,而是定义数据;当数据变化时,框架自动更新视图。开发者只需思考"业务状态是什么",而非"页面该怎么改"。
响应式状态:用 ref 管理数据
在 Vue 3 的 <script setup> 中,我们使用 ref 创建响应式变量:
php
<script setup>
import { ref } from 'vue'
const title = ref('Todos 任务清单')
const todos = ref([
{ id: 1, title: '打王者', done: false },
{ id: 2, title: '吃饭', done: true }
])
</script>
title 和 todos 都是响应式引用对象。通过 title.value = '新标题' 修改值后,模板中所有使用 {{ title }} 的地方都会自动刷新。这种机制将 UI 与状态紧密绑定,消除了手动 DOM 操作的繁琐。
模板指令:简洁表达逻辑
Vue 提供一系列指令,以声明方式描述 UI 行为:
ini
<input v-model="title" @keyup.enter="addTodo" />
<ul v-if="todos.length">
<li v-for="todo in todos" :key="todo.id">
<input type="checkbox" v-model="todo.done" />
<span :class="{ 'done': todo.done }">{{ todo.title }}</span>
</li>
</ul>
v-model实现双向绑定,输入框内容与title同步;@keyup.enter监听回车键,触发添加任务;v-for循环渲染列表,无需手动拼接 HTML;:class动态绑定样式,完成项显示删除线;v-if控制"暂无任务"提示的显示时机。
这些指令将常见交互模式封装成语义化语法,大幅降低样板代码量。
计算属性:高效派生状态
任务清单需要实时显示"未完成任务数"和"全选"状态。若在模板中直接写 todos.filter(...).length,每次渲染都会重新计算,影响性能。Vue 的 computed 提供了缓存机制:
ini
const active = computed(() => {
return todos.value.filter(todo => !todo.done).length
})
active 是一个计算属性,只有当 todos 发生变化时才会重新求值。模板中使用 {{ active }} 即可获得最新结果,且性能最优。
更巧妙的是,computed 支持 getter/setter,可用于实现"全选"功能:
javascript
const allDone = computed({
get() {
return todos.value.every(todo => todo.done)
},
set(value) {
todos.value.forEach(todo => todo.done = value)
}
})
当用户勾选"全选"复选框时,set 被调用,批量更新所有任务状态;反之,若部分任务被取消,get 返回 false,复选框自动取消。这种双向联动仅需几行代码,却覆盖了复杂的交互逻辑。
添加任务:聚焦数据变更
新增任务的本质是向 todos 数组追加一项:
php
const addTodo = () => {
if (!title.value.trim()) return
todos.value.push({
id: Date.now(),
title: title.value,
done: false
})
title.value = ''
}
这里没有 createElement、appendChild 或 innerHTML,只有对数据的操作。Vue 会自动检测数组变更,并高效更新 DOM。这种"数据即 UI"的思想,让业务逻辑与视图完全解耦。
样式与体验优化
通过动态类名,轻松实现视觉反馈:
css
.done {
color: #999;
text-decoration: line-through;
}
配合 :class="{ 'done': todo.done }",完成的任务自动变灰并加删除线,提升用户体验。
总结
这个 Todos 应用虽小,却完整展示了 Vue 3 的核心优势:
- 响应式系统让状态与视图自动同步;
- 组合式 API 提供灵活、可复用的逻辑组织方式;
- 模板指令 将常见交互抽象为简洁语法;
- 计算属性 在保证性能的同时简化派生状态管理。
相比传统 DOM 操作,Vue 让开发者从"如何改页面"转向"数据该是什么样",极大降低了心智负担。对于初学者,这是快速上手现代前端开发的捷径;对于资深工程师,这是构建可维护、可扩展应用的坚实基础。正如那句老话:"当你专注于数据,UI 自会跟随。"