4. 响应式数据
这是什么:响应式数据 = 被 Vue「盯上」的数据,一旦值变了,引用它的视图就自动重算更新。
为什么用:上一章模板里输入框的内容会变,但那只是 v-model 的功劳。想让自己的数据驱动页面,得先把数据包成响应式。
如何用:本章从 ref() 包单个值讲到 computed 和 watch,先跑一个点击加一的计数器。
4.1 ref:单个值的响应式包装
完整页面(可直接贴进运行场,试试连点):
<!DOCTYPE html>
<html lang='zh-CN'>
<head>
<meta charset='utf-8'>
<title>ref 计数器</title>
<script src='https://registry.npmmirror.com/vue/3.5.44/files/dist/vue.global.prod.js'></script>
</head>
<body>
<div id='app'>
<button @click='add'>点了我 {{ count }} 次</button>
</div>
<script>
const { createApp, ref } = Vue
createApp({
setup() {
const count = ref(0)
function add() {
count.value++ // JS 里逢读写用 .value
}
return { count, add }
}
}).mount('#app')
</script>
</body>
</html>
要点:
ref(0)把 0 包成响应式对象- 在 JS 里读写都要
.value - 在模板里自动解包,直接写
{{ count }}(别加 .value)
「模板自动解包」新手最容易混。口诀:JS 里 .value,模板里裸用。
4.2 reactive:对象的响应式
<script>
const { reactive } = Vue
const user = reactive({ name: '青蛙', age: 11 })
user.age = 12 // 直接改属性即可,不用 .value
</script>
| 对比 | ref | reactive |
|---|---|---|
| 适合 | 单值 / 需整体替换 | 固定结构的对象 |
| 访问 | .value |
直接 obj.xxx |
| 替换自身 | 可以 ref = ref(新值) |
不可整体替换(响应性会丢失) |
教学建议:入门阶段简单场景统一用 ref,对象也 ref() 包起来,心智负担最小。
4.3 computed:由数据算出来的值
<script>
const { ref, computed } = Vue
const tasks = ref(['a', 'b', 'c'])
const done = ref(1)
const percent = computed(() =>
Math.round((done.value / tasks.value.length) * 100)
)
</script>
配合模板:<p>完成度:{{ percent }}%</p>。
computed 会缓存:依赖(tasks/done)不变时反复显示不重算。
4.4 watch:数据变化时执行副作用
computed 算值;watch 干活(请求、日志、localStorage 存储):
<script>
const { ref, watch } = Vue
const msg = ref('')
watch(msg, (newValue, oldValue) => {
console.log(`从 ${oldValue} 变成 ${newValue}`)
})
</script>
4.5 动手改
- 写 count + 按钮,每点击一次 +10,用 computed 显示是否超过 50
- 给 user 对象加 city 并在模板中显示
- watch msg,输入长度超 20 时 console 警告(记得在运行场里看输出区)
4.6 小结
- 免构建写法开头一句:
const { createApp, ref } = Vue——从全局Vue对象解构,代替工程写法的import - ref 包值,JS 里
.value、模板裸用 - reactive 包对象,属性直改不换壳
- computed 算、watch 干活
下一章:事件与方法 🐸