1-3 响应式 API:ref / reactive / computed / watch
配套 Demo
这一章讲 Vue 3 的「数据层」四大件。掌握它们,你就能优雅地组织组件的状态和派生逻辑。
配套 demo:
demo/1-3-reactivity.html(一个简单购物车,综合演示四者)。
1. ref——包装单个值
1-1 见过了。适合单个值:数字、字符串、布尔,也能放对象。
js
const count = ref(0);
const name = ref('张三');
count.value++; // JS 里要 .value口诀重申:JS 里带 .value,模板里不带。
2. reactive——包装一个对象
当一组数据天然属于一个对象时,用 reactive 更顺手。它不需要 .value:
js
const form = reactive({
username: '',
password: '',
remember: false,
});
form.username = '张三'; // 直接改,不用 .value模板里:
html
<input v-model="form.username">
<p>{{ form.username }}</p>ref vs reactive 怎么选?
ref | reactive | |
|---|---|---|
| 适合 | 单个值(数字/字符串/布尔) | 一组相关字段的对象 |
| 访问 | JS 里要 .value | 直接 .属性 |
| 能否整体替换 | x.value = 新对象 ✅ | 不能 obj = 新对象(会丢响应式) |
实战建议:新手统一用
ref就行,连对象也能放(ref({...}),JS 里obj.value.xxx)。等熟练了再按喜好用reactive。本教程后续多数用ref。
⚠️ reactive 的坑:不能整体重新赋值。form = reactive({...}) 会让响应式失效。要换整个对象,用 ref 更省心。
3. computed——计算属性(派生数据)
当某个值是由其它响应式数据算出来的,用 computed,别用普通函数或变量。
js
const price = ref(10);
const count = ref(3);
// 总价由 price 和 count 派生
const total = computed(() => price.value * count.value);html
<p>总价:{{ total }}</p> <!-- price 或 count 变,total 自动重算 -->后端类比:computed 就是一个带缓存的 getter。
为什么不用普通函数?
computed 有缓存:只要依赖(price/count)没变,多次读取不会重复计算。而普通方法每次调用都重算。性能更好,语义也更清晰。
js
// ❌ 方法:每次模板用到都重新执行
function total() { return price.value * count.value; }
// ✅ computed:依赖不变就用缓存
const total = computed(() => price.value * count.value);经验:「界面上要显示的、由别的数据算出来的值」,优先用 computed。 比如:筛选后的列表、合计金额、是否全选、表单是否合法……
可写的 computed(进阶,先了解)
js
const fullName = computed({
get: () => firstName.value + lastName.value,
set: (val) => { /* 拆开赋值回去 */ }
});4. watch——侦听器(数据变了去做副作用)
computed 是「算出一个值」;watch 是「数据变了,去做一件事」(发请求、存本地、打日志等副作用)。
js
const keyword = ref('');
// 监听 keyword,变了就执行回调
watch(keyword, (newVal, oldVal) => {
console.log(`从「${oldVal}」变成「${newVal}」`);
// 比如:去后端搜索
});监听多个 / 监听对象属性
js
// 监听多个
watch([a, b], ([newA, newB]) => { ... });
// 监听 reactive 对象的某个属性,要用函数形式
watch(() => form.username, (val) => { ... });watch 的选项
js
watch(keyword, callback, {
immediate: true, // 一进来就先执行一次(默认是变化时才执行)
deep: true, // 深度监听对象内部属性变化
});computed vs watch 怎么选?
- 要得到一个新值显示在界面上 →
computed - 数据变化时要执行一段操作(请求、保存、跳转)→
watch
口诀:算值用 computed,办事用 watch。
动手练习(用 demo/1-3-reactivity.html)
demo 是个购物车,数量可加减:
- 改数量,观察「小计」和「总价」自动更新(
computed)。 - 打开 F12 Console,改数量时会看到 watch 打印的日志(
watch监听总价变化)。 - 把某商品数量加到很大,看「是否享受满减」提示出现(又一个 computed)。
- 试着自己加一个 computed:
itemCount(商品种类数),显示在界面上。
小结
| API | 用途 | 关键点 |
|---|---|---|
ref | 单个响应式值 | JS 里 .value,模板里不用 |
reactive | 响应式对象 | 直接改属性,不能整体替换 |
computed | 派生值(带缓存) | 由别的数据算出来的值用它 |
watch | 数据变化时做副作用 | 请求/保存/跳转用它 |
➡️ 下一章:1-4 组件化:props / emit / slot