“我写 JS 就是为了不写 JS。”
🧠 从前,我们这样写 TodoList...
还记得刚学前端时,你是怎么实现一个简单的待办事项(TodoList)的吗?
const app = document.getElementById('app');
const todoInput = document.getElementById('todo-input');
todoInput.addEventListener('change', function(event) {
const todo = event.target.value.trim();
if (!todo) {
console.log('请输入任务');
return;
}
app.innerHTML = todo;
});
是不是感觉像在给浏览器“下命令”?
先找元素 → 再监听事件 → 然后改内容 → 最后祈祷别出 bug。
这种命令式编程,就像你对机器人说:“去厨房,打开冰箱,拿出可乐,拧开瓶盖,倒进杯子,端给我。”
而 Vue 想说的是: “我要喝可乐。” ——剩下的,它来搞定。
✨ Vue 的哲学:数据驱动一切
Vue 的核心思想就一句话:
“你只管关心数据怎么变,DOM 怎么更新?那是我的事。”
这叫 响应式数据驱动。
你不再需要思考“怎么改页面”,而是思考“数据应该变成什么样”。
比如:
- 用户输入新任务 →
todos数组加一项 - 勾选完成 → 对应
done变成true - 全选 → 所有
done都设为true
DOM 自动跟着变,连 CSS 动画都省了!
🧪 Vue3 Composition API:更清爽的代码体验
Vue3 引入了 Composition API(组合式 API),让逻辑组织更清晰、复用更容易。
来看一个标准的 TodoList 组件骨架:
<script setup>
import { ref, computed } from 'vue'
// 响应式数据
const title = ref('')
const todos = ref([
{ id: 1, title: '打王者', done: false },
{ id: 2, title: '吃饭', done: false }
])
// 添加任务
const addTodo = () => {
if (!title.value.trim()) return
todos.value.push({
id: Math.random(),
title: title.value,
done: false
})
title.value = ''
}
// 计算属性:未完成数量
const active = computed(() =>
todos.value.filter(todo => !todo.done).length
)
// 全选/反选(带 getter/setter 的 computed)
const allDone = computed({
get() {
return todos.value.length > 0 && todos.value.every(t => t.done)
},
set(val) {
todos.value.forEach(t => t.done = val)
}
})
</script>
是不是比 document.getElementById 清爽一百倍?
而且逻辑集中、变量明确、复用方便——这才是现代前端该有的样子!
🔥 关键指令速览:Vue 的“魔法咒语”
| 指令 | 作用 | 类比 |
|---|---|---|
v-model | 双向绑定输入框 | “你打字,我自动记下来” |
v-for | 循环渲染列表 | “有多少数据,我就画多少行” |
v-if / v-else | 条件渲染 | “没任务?那我就躺平显示‘暂无计划’” |
@keydown.enter | 监听回车 | “按回车?懂了,马上加任务!” |
:class | 动态样式 | “完成的任务?灰掉+删除线,安排!” |
这些指令,本质上就是 Vue 给你封装好的“快捷操作包”。
你不用再写 element.classList.add('done'),只需一句:
<span :class="{ done: todo.done }">{{ todo.title }}</span>
优雅,永不过时。
💡 computed:性能优化的秘密武器
很多人以为 computed 只是“把函数结果缓存一下”,其实它更厉害:
- 依赖追踪:只有依赖的数据变了,才重新计算。
- 自动缓存:多次访问不会重复执行。
- 支持 setter:可以反向修改原始数据(比如全选功能)。
比如这个 active:
const active = computed(() =>
todos.value.filter(todo => !todo.done).length
)
即使你在模板里写了十次 {{ active }},它也只算一次。
而如果你直接写 {{ todos.filter(...).length }},每次渲染都会重新过滤——性能杀手!
🎨 模板长这样(简洁又强大)
<template>
<div>
<h2>{{ title }}</h2>
<input v-model="title" @keydown.enter="addTodo" placeholder="输入任务,回车添加">
<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>
<div v-else>暂无计划(摸鱼中...)</div>
<div>
<label>
<input type="checkbox" v-model="allDone"> 全选
</label>
{{ active }} / {{ todos.length }}
</div>
</div>
</template>
<style scoped>
.done {
color: gray;
text-decoration: line-through;
}
</style>
短短几十行,完成了:
- 输入回车添加
- 列表渲染
- 完成状态切换
- 全选/反选
- 实时统计
- 样式联动
这效率,老板看了想加薪,同事看了想抄代码。
🤔 为什么 Vue 更适合新手?
- 降低心智负担:不用记 DOM API,专注业务逻辑。
- 错误更少:避免手误拼错
getElementById。 - 开发更快:声明式语法,所见即所得。
- 调试更爽:DevTools 直接看响应式数据变化。
就像你不需要会造汽车,也能开车上路。Vue 就是你的“自动驾驶系统”。
🚀 结语:从“操作 DOM”到“操控数据”
传统开发: “我要让那个 div 变红!”
Vue 开发: “这个状态是 error,UI 自己知道该怎么做。”
真正的前端高手,不是 DOM 操作多熟练,而是能把复杂逻辑抽象成清晰的数据流。
所以,下次写 TodoList 时,别再 querySelector 了。
打开 Vue,写一行 ref,剩下的——交给框架,你去摸鱼。
毕竟,程序员的终极目标,是让代码自己干活。