一、情景说明
在Vue2
中,我们已经知道数据的响应式,是什么含义
就是,在data
块中,定义的变量,在页面中引用后
任何地方修改了该变量,页面中引用的变量会立即显示最新数值。
这块,我们学习了
插值语法:{``{}}
单向绑定指令:v-bind
双向绑定指令:v-model
那么,在Vue3
中,没有了data
块,如何实现数据的响应式了?
二、响应式数据
Person.vue
组件
html
<template>
<div class="person">
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<h2>地址:{{address}}</h2>
<button @click="changeName">修改名字</button>
<button @click="changeAge">修改年龄</button>
<button @click="showTel">查看联系方式</button>
</div>
</template>
<script lang="ts" setup name="Person">
// 数据,原来是写在data中的,此时的name、age、tel都不是响应式的数据
let name = '张三'
let age = 18
let tel = '13888888888'
let address = '北京昌平区宏福苑·宏福科技园'
// 方法
function changeName() {
name = 'zhang-san' //注意:这样修改name,页面是没有变化的
console.log(name) //name确实改了,但name不是响应式的
}
function changeAge() {
age += 1 //注意:这样修改age,页面是没有变化的
console.log(age) //age确实改了,但age不是响应式的
}
function showTel() {
alert(tel)
}
</script>
1、ref实现基本类型的数据响应式
针对上面的组件,我们想要实现name、age
两个变量的数据响应式效果。
script
引用函数:
javascript
import {ref} from 'vue'
创建变量:
javascript
let name = ref('张三')
let age = ref(18)
读取变量:
html
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
修改变量:
JS
中操作ref
创建的变量时候需要.value
javascript
// 方法
function changeName() {
name.value = 'zhang-san'
}
function changeAge() {
age.value += 1
}
2、ref实现对象类型的数据响应式
底层是reactive
实现的功能
script
引用函数:
javascript
import {ref} from 'vue'
创建变量:
javascript
let car = ref({brand:'奔驰',price:100})
let games = ref([
{id:'aysdytfsatr01',name:'王者荣耀'},
{id:'aysdytfsatr02',name:'原神'},
{id:'aysdytfsatr03',name:'三国志'}
])
读取变量:
html
<h2>汽车信息:一辆{{car.brand}}车,价值{{car.price}}万</h2>
<li v-for="g in games" :key="g.id">{{g.name}}</li>
修改变量:
JS
中操作ref
创建的变量时候需要.value
javascript
function changePrice(){
car.value.price += 10
console.log(car.value.price)
}
function changeFirstGame(){
games.value[0].name = '流星蝴蝶剑'
}
3、reactive实现对象类型的数据响应式
script
引用函数:
javascript
import {reactive} from 'vue'
创建变量:
创建了3个响应式对象数据
javascript
// 数据
// 单个对象数据
let car = reactive({brand:'奔驰',price:100})
// 数组型对象
let games = reactive([
{id:'aysdytfsatr01',name:'王者荣耀'},
{id:'aysdytfsatr02',name:'原神'},
{id:'aysdytfsatr03',name:'三国志'}
])
// 多层次对象
let obj = reactive({
a:{
b:{
c:666
}
}
})
读取变量:
html
<h2>汽车信息:一辆{{car.brand}}车,价值{{car.price}}万</h2>
<li v-for="g in games" :key="g.id">{{g.name}}</li>
<h2>测试:{{obj.a.b.c}}</h2>
修改变量:
javascript
// 方法
function changePrice(){
car.price += 10
console.log(car.price)
}
function changeFirstGame(){
games[0].name = '流星蝴蝶剑'
}
function changeObj(){
obj.a.b.c = 999
}
4、注意事项
reactive
创建的对象变量,被重新分配一个新对象时,会失去 响应式效果
ref
创建的对象类型变量,不存在这个问题。
问题重现:
reactive定义一个对象类型的变量
javascript
let car = reactive({brand:'奔驰',price:100})
需求:
给car重新赋值一个对象
无效写法:
javascript
car = {brand:'奥拓',price:1}
car = reactive({brand:'奥拓',price:1})
有效写法:
javascript
Object.assign(car,{brand:'奥拓',price:1})
三、对比
- 宏观角度看:
ref
用来定义:基本类型数据 、对象类型数据;
reactive
用来定义且只能定义:对象类型数据。
- 区别:
ref
创建的变量必须使用.value
(可以使用volar
插件自动添加.value
)。reactive
重新分配一个新对象,会失去 响应式(可以使用Object.assign
去整体替换)。
- 使用原则:
- 若需要一个基本类型的响应式数据,必须使用
ref
。- 若需要一个响应式对象,层级不深,
ref
、reactive
都可以。- 若需要一个响应式对象,且层级较深,推荐使用
reactive
。