Skip to content

1-3 响应式 API:ref / reactive / computed / watch

这一章讲 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 怎么选?

refreactive
适合单个值(数字/字符串/布尔)一组相关字段的对象
访问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 是个购物车,数量可加减:

  1. 改数量,观察「小计」和「总价」自动更新(computed)。
  2. 打开 F12 Console,改数量时会看到 watch 打印的日志(watch 监听总价变化)。
  3. 把某商品数量加到很大,看「是否享受满减」提示出现(又一个 computed)。
  4. 试着自己加一个 computed:itemCount(商品种类数),显示在界面上。

小结

API用途关键点
ref单个响应式值JS 里 .value,模板里不用
reactive响应式对象直接改属性,不能整体替换
computed派生值(带缓存)由别的数据算出来的值用它
watch数据变化时做副作用请求/保存/跳转用它

➡️ 下一章:1-4 组件化:props / emit / slot

写给有后端基础、想系统学习 Vue 3 与 H5 的开发者