——一次从命令式到响应式的精神迁移之旅
你第一次写前端是什么体验?
可能是这样的:
const app = document.getElementById('app')
app.innerHTML = '吃饭睡觉打豆豆'
写完之后你突然意识到 ——
我不是在写页面,而是在和 DOM 谈恋爱。
你要知道:
DOM 是浏览器里最慢、最难哄、最容易甩脸子的那个家伙。
于是,在 2024 年的某一天,人类工程师们受不了了:
“能不能别天天操作 DOM?我只是想改个标题,你却逼我写 50 行命令式代码?”
然后 Vue 说话了:
🧘♂️ 别找 DOM。找我就够了。只要你告诉我数据怎么变,我来负责界面怎么更新。
好家伙,这谁顶得住。
本文就带你重新理解:
Vue 的开发思路为什么这么丝滑?为什么响应式能改变整个前端编程方式?
并结合一个 Todo 例子讲透 Vue 3 的核心模型。
🍃 1. 命令式 vs 响应式:不是语法差异,是“人生哲学”的差异
先看传统写法👇
<h2 id="app"></h2>
<input type="text" id="todo-input">
<script>
const app = document.getElementById('app');
const todoInput = document.getElementById('todo-input');
todoInput.addEventListener('change', function (event) {
const todo = event.target.value.trim();
if (!todo) return;
app.innerHTML = todo;
})
</script>
它的问题是:
- 每次做事都要先拿到 DOM
- 再判断是否该改 DOM
- 再改 DOM
- 你一旦写多了,就是“命令式地折磨自己”
就像你开车时还要不断告诉发动机:“兄弟,油门踩一点,方向往左两度”。
你不累,但发动机累。
🟩 Vue 的做法:
别告诉我页面怎么改,告诉我“数据要变成什么样”就行。
比如我们写标题:
<h2>{{ title }}</h2>
<input v-model="title">
因为 Vue 内部有一整套:
- 响应式系统
- 依赖追踪
- 虚拟 DOM diff
- 批量更新机制
它会自动做到:
- 你改数据 → Vue 追踪变化
- 模板依赖了这个数据 → 触发更新
- DOM → Vue 帮你改
你就负责说你想要什么,Vue 负责告诉世界应该怎样改变。
这不是框架,这是 一种新的世界观。
🍙 2. ref:Vue 响应式的最小颗粒度
Vue Composition API 的核心:
import { ref } from 'vue'
const title = ref("")
为什么要 ref?
因为 Vue 内部用 Proxy 包装了这个值,当你:
title.value = "吃饭"
Vue 就会对模板喊一句:
“嘿,模板!依赖 title 的地方都准备一下,我要更新了!”
于是界面自动更新。
你只修改数据,Vue 来干脏活累活 ——
这就叫“响应式数据驱动视图”。
🍱 3. v-if、v-for、v-model:Vue 的三把神剑
Vue 全靠响应式,却拥有极爽的 API:
🔪 v-if:逻辑表达式决定结构是否渲染
<ul v-if="todos.length">
如果没有任务,渲染“暂无计划”。
如果你用原生写?不好意思,又要写:
if (...) {
element.style.display = ...
}
🔪 v-for:最舒服的循环表达式
<li v-for="todo in todos" :key="todo.id">
循环与 key 配合,纯文本描述 UI,
你关注的是 “要显示哪些数据” ,
而不是 “要生成多少 DOM” 。
🔪 v-model:双向绑定的灵魂伴侣
<input v-model="title">
输入框与数据自动同步。
你永远不用写:
input.addEventListener('input'...)
这不是 API 简单,是 理念先进。
🥟 4. methods + computed:逻辑与性能的完美组合
Vue 里计算逻辑有两种:
🧮 方式 1:方法(每次渲染就执行一次)
{{ todos.filter(todo => !todo.done).length }}
缺点:
只要组件内任何响应式数据变了,就会重新计算。
即使变化的不是 todos。
(因为方法没有依赖追踪能力)
🧮 方式 2:computed(有缓存,自动依赖追踪)
const active = computed(() => {
return todos.value.filter(todo => !todo.done).length
})
computed 的魔力:
- 它知道自己依赖了
todos - 只有 todos 变化才会重新计算
- 否则直接走缓存
性能更好,逻辑更干净,完全自动化。
✨ 双向 computed:神奇的 get/set
比如全选:
const allDone = computed({
get(){
return todos.value.every(todo => todo.done)
},
set(val){
todos.value.forEach(todo => todo.done = val)
}
})
配合模板:
<input type="checkbox" v-model="allDone">
于是:
- 全选 → set 全部勾选
- 全部勾选 → get 返回 true
- 任意取消 → get 变成 false → Checkbox 取消
逻辑写在数据里,UI 自动反映数据状态。
🍵 5. Vue 的开发思路总结:写 Vue,就是写“数据怎么变”
来,把最核心的一句话写大一点👇
🟦 Vue 不是让你写界面,而是让你写:数据应该如何存在、如何改变。
🟦 剩下的 DOM 操作,Vue 全帮你包办了。
所以 Vue 开发的心法:
✔ 关注业务数据
什么字段?怎么变化?变化条件是什么?
✔ 模板只是数据的投影
模板不写逻辑,只写“界面长什么样”。
✔ 事件负责触发数据变化
不要操作 DOM,只让数据改。
✔ 响应式负责联动更新
Vue 自动管理 DOM 优化、渲染时机、diff、合并更新。
✔ computed 专注“派生数据”
不用重复写逻辑,不用担心性能。
🧁 6. 上手 Vue = 上手一种更高级的思考方式
如果你把 Vue 和传统命令式对比,会发现:
| 方向 | 命令式 | 响应式(Vue) |
|---|---|---|
| 思维方式 | “我要操作谁?” | “我想让数据变成什么?” |
| 心智负担 | 大 | 小 |
| DOM 操作 | 手动完成 | 框架接管 |
| 性能 | 容易写出低效代码 | 内置优化 |
| 可维护性 | 乱 | 稳 |
| 初学门槛 | 奇高(操作 DOM) | 入门即高质量 |
Vue 就像你给前端编程装上了自动挡。
你不再需要时刻想着挡位、油门、离合。
你只需要说:
“我要去哪。”
Vue 说:
✨“我带你飞。”✨
🍰 7. 完整示例(你已经能看懂 100% 了)
你提供的 Demo,其实已经体现了:
- 响应式 ref
- 模板绑定
- v-if / v-for
- v-model
- computed
- composition API 写法
- 从命令式到响应式的思维转换
你已经抓住了 Vue 的灵魂。
🌈 8. 为什么人人都爱 Vue?
因为对大多数前端工程师来说:
✖ 我只是想更新标题
✔ 我不想操作 DOM
✖ 我只是想做一个“条件显示”
✔ 我不想判断 display
✖ 我只是想统计未完成任务
✔ 我不想每次渲染都重新计算
✖ 我只是想双向绑定数据
✔ 我不想写 addEventListener
Vue 用一种极其优雅的方式解决了这些开发痛点。
最终实现了一个前端框架的终极目标: