开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第10天,点击查看活动详情
在vue2中定义数据在模板中使用的时候,只要不是那几种特殊情况,正常定义数据都是响应式的,但是在vue3中是不一样的,如果直接用=定义数据变量是不具有响应式的。
定义响应式数据
在使用ref和reactive定义响应式数据的时候,它们的使用场景是不一样的。
1. ref
1.1 使用方法
定义基本类型数据
<div>{{school}}学生信息</div>
<button @click="updateInfo">修改信息</button>
import { ref } from 'vue';
const school = ref('高级中学');
console.log('school', school);
const updateInfo = () => {
school.value = '附属中学';
console.log('school', school);
}
效果如下:
可以看出ref就是将基础数据转换为响应式数据,把数据包装成响应式的引用数据类型的数据。
修改ref定义的值需要使用.value去操作,效果如下:
定义复杂类型数据
<div>姓名:{{person.name}}</div>
<div>年龄:{{person.age}}</div>
<div>朋友:{{person.friend.name}}-{{person.friend.age}}</div>
<div v-for="(item, index) in person.hobbies" :key="index">爱好列表
<div>{{item}}</div>
</div>
<button @click="updateInfo">修改信息</button>
import { ref } from 'vue';
const person = ref({
name: '艾薇儿',
age: 18,
friend: {
name: '安妮·海瑟薇',
age: '28'
},
hobbies: ['music', 'dance', 'movie']
})
console.log('person', person);
const updateInfo = () => {
person.value.friend.name = '麻子';
person.value = {
name: '疯驴子',
age: 25,
friend: {
name: '高启强',
age: '28'
},
hobbies: ['music', 'dance', 'movie']
}
console.log('person', person);
}
效果如下:
可以看出使用ref定于复杂类型数据时是会将复杂类型对象使用Proxy转成响应式对象的,但是对于响应式对象我们不建议使用ref,应该有一个更适合的方式就是下面介绍的reactive。
修改对象值后效果如下:
1.2 使用场景
- 用来定义基本数据类型
- 在修改值和获取值的时候需要使用.value,在模板中是不需要使用.value
2. reactive
2.1 使用方法
<div>姓名:{{person.name}}</div>
<div>年龄:{{person.age}}</div>
<div>朋友:{{person.friend.name}}-{{person.friend.age}}</div>
<div v-for="(item, index) in person.hobbies" :key="index">爱好列表
<div>{{item}}</div>
</div>
<button @click="updateInfo">修改信息</button>
import { reactive } from 'vue';
let person = reactive({
name: '艾薇儿',
age: 18,
friend: {
name: '安妮·海瑟薇',
age: '28'
},
hobbies: ['music', 'dance', 'movie']
})
console.log('person', person);
const updateInfo = () => {
person = {
name: '疯驴子',
age: 25,
friend: {
name: '高启强',
age: '28'
},
hobbies: ['music', 'dance', 'movie']
}
console.log('person', person);
}
效果如下:
从上述效果图我们可以看出,使用reactive定义的数据会转成响应式对象(proxy)。但是如果直接修改这个对象响应式是会失效的,即使数据内容变量,视图也不会更新。如果修改对象的属性,那么视图是会及时更新的。
效果如下:
2.2 响应式会失效的情况
像上述对对象直接赋值,响应式是会生效的。除了直接赋值之外,响应式还会生效有以下几种情况:
2.2.1 重新赋值
上述针对复杂类型的数据,如果重新赋值的话,相当于是将变量的引用指向了另外一个地址,而这个地址对象是新加的,没有通过reactive进行代理,所以不具有响应式。
针对上述情况,可以通过以下方法使其继续变成响应式数据。
给对象添加一个属性
<div>姓名:{{person.data.name}}</div>
<div>年龄:{{person.data.age}}</div>
<div>朋友:{{person.data.friend.name}}-{{person.data.friend.age}}</div>
<div v-for="(item, index) in person.data.hobbies" :key="index">爱好列表
<div>{{item}}</div>
</div>
<button @click="updateInfo">修改信息</button>
import { reactive } from 'vue';
let person = reactive({
data: {
name: '艾薇儿',
age: 18,
friend: {
name: '安妮·海瑟薇',
age: '28'
},
hobbies: ['music', 'dance', 'movie']
}
})
console.log('person', person);
const updateInfo = () => {
person.data = {
name: '疯驴子',
age: 25,
friend: {
name: '高启强',
age: '28'
},
hobbies: ['music', 'dance', 'movie']
}
console.log('person', person);
}
初始效果如下:
修改之后效果如下:
使用Object.assign()
2.2.2 解构
<div>姓名:{{name}}</div>
<div>年龄:{{age}}</div>
<div>朋友:{{friend.name}}-{{friend.age}}</div>
<div v-for="(item, index) in hobbies" :key="index">爱好列表
<div>{{item}}</div>
</div>
<button @click="updateInfo">修改信息</button>
import { reactive } from 'vue';
let person = reactive({
name: '艾薇儿',
age: 18,
friend: {
name: '安妮·海瑟薇',
age: '28'
},
hobbies: ['music', 'dance', 'movie']
});
const { name, age, friend, hobbies} = person;
console.log('person', person);
const updateInfo = () => {
person.name = '疯驴子';
console.log('person', person);
}
效果如下:
从上述效果图中可以看出解构赋值后失去了响应式。解构赋值中对于基本数据类型是按值传递,对于引用类型是按引用传递。name虽然是person.name的值,但是访问name的时候绕过了对象的get方法,因此失去了响应式,如果是按引用类型来传递的话就不会失去响应式。
2.2 使用场景
- 用来定义复杂数据类型
- 定义数组的时候需要