用 Vue 3 构建任务清单:响应式编程的优雅实践

在前端开发中,任务清单(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>

titletodos 都是响应式引用对象。通过 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 = ''
}

这里没有 createElementappendChildinnerHTML,只有对数据的操作。Vue 会自动检测数组变更,并高效更新 DOM。这种"数据即 UI"的思想,让业务逻辑与视图完全解耦。

样式与体验优化

通过动态类名,轻松实现视觉反馈:

css 复制代码
.done {
  color: #999;
  text-decoration: line-through;
}

配合 :class="{ 'done': todo.done }",完成的任务自动变灰并加删除线,提升用户体验。

总结

这个 Todos 应用虽小,却完整展示了 Vue 3 的核心优势:

  • 响应式系统让状态与视图自动同步;
  • 组合式 API 提供灵活、可复用的逻辑组织方式;
  • 模板指令 将常见交互抽象为简洁语法;
  • 计算属性 在保证性能的同时简化派生状态管理。

相比传统 DOM 操作,Vue 让开发者从"如何改页面"转向"数据该是什么样",极大降低了心智负担。对于初学者,这是快速上手现代前端开发的捷径;对于资深工程师,这是构建可维护、可扩展应用的坚实基础。正如那句老话:"当你专注于数据,UI 自会跟随。"

相关推荐
夏幻灵1 天前
HTML5里最常用的十大标签
前端·html·html5
Mr Xu_1 天前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js
未来龙皇小蓝1 天前
RBAC前端架构-01:项目初始化
前端·架构
程序员agions1 天前
2026年,微前端终于“死“了
前端·状态模式
万岳科技系统开发1 天前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
程序员猫哥_1 天前
HTML 生成网页工具推荐:从手写代码到 AI 自动生成网页的进化路径
前端·人工智能·html
龙飞051 天前
Systemd -systemctl - journalctl 速查表:服务管理 + 日志排障
linux·运维·前端·chrome·systemctl·journalctl
我爱加班、、1 天前
Websocket能携带token过去后端吗
前端·后端·websocket
AAA阿giao1 天前
从零拆解一个 React + TypeScript 的 TodoList:模块化、数据流与工程实践
前端·react.js·ui·typescript·前端框架
杨超越luckly1 天前
HTML应用指南:利用GET请求获取中国500强企业名单,揭秘企业增长、分化与转型的新常态
前端·数据库·html·可视化·中国500强