vue3.x之ref和reactive函数
在vue2中定义数据在模板中使用的时候,只要不是那几种特殊情况,正常定义数据都是响应式的,但是在vue3中是不一样的,如果直接用=定义数据变量是不具有响应式的。
定义响应式数据
在使用ref和reactive定义响应式数据的时候,它们的使用场景是不一样的。
1. ref
使用方法
⏰ 定义基本类型数据
<template> <header> <div>{{ school }}</div> <button @click="updateInfo">修改信息</button> </header> </template> <script lang="ts"> //👀:需要什么导入什么 import { ref } from 'vue' export default { name: 'App', //setup函数是组合式API的入口函数,调用在beforeCreated之前 setup() { //1.定义响应式变量 const school = ref('高级中学'); console.log('school',school); //2.定义函数 const updateInfo = ()=>{ school.value = '附属中学' console.log('school',school); } //3.将相关属性,函数,暴露给外界方便使用 return { school, updateInfo } } } </script>
效果如下:
❗️可以看出ref就是将基础数据转换为响应式数据,把数据包装成响应式的引用数据类型的数据。
修改ref定义的值需要使用.value去操作,效果如下:

⏰定义复杂类型数据
<template> <div>姓名:{{ person.name }}</div><br> <div>年龄:{{ person.age }}</div><br> <div>朋友:{{ person.friend.name }} - {{ person.friend.age }}</div><br> <div v-for="(item,index) in person.hobbies" :key="index"> <div>{{ item }}</div> </div><br> <button @click="updateInfo">修改信息</button> </template> <script lang="ts"> //👀:需要什么导入什么 import { ref } from 'vue' export default { name: 'App', //setup函数是组合式API的入口函数,调用在beforeCreated之前 setup() { //1.定义响应式变量 const person = ref({ name:'艾薇儿', age:18, friend:{ name:'安妮.海瑟薇', age:'28' }, hobbies: ['music', 'dance', 'movie'] }) console.log('person',person); //2.定义函数 const updateInfo = ()=>{ person.value.friend.name = '王麻子'; person.value = { name:'张赖子', age:25, friend:{ name:'疯驴子', age:'28' }, hobbies:['music','dance','movie'] } console.log('person',person); } //3.将相关属性,函数,暴露给外界方便使用 return { person, updateInfo } } } </script>
效果如下:

可以看出使用ref定于复杂类型数据时是会将复杂类型对象使用Proxy转成响应式对象的,但是对于响应式对象我们不建议使用ref,应该有一个更适合的方式就是下面介绍的reactive。
修改对象值后效果如下:

使用场景
1. 用来定义基本数据类型
2. 在修改值和获取值的时候需要使用.value,在模板中是不需要使用.value
2. reactive
使用方法
⏰定义复杂类型数据
<template> <div>姓名:{{ person.name }}</div><br> <div>年龄:{{ person.age }}</div><br> <div>朋友:{{ person.friend.name }} - {{ person.friend.age }}</div><br> <div v-for="(item, index) in person.hobbies" :key="index"> <div>{{ item }}</div> </div><br> <button @click="updateInfo">修改信息</button> </template> <script lang="ts"> //👀:需要什么导入什么 import { reactive } from 'vue' export default { name: 'App', //setup函数是组合式API的入口函数,调用在beforeCreated之前 setup() { //1.定义响应式变量 let person = reactive({ name: '艾薇儿', age: 18, friend: { name: '安妮.海瑟薇', age: '28' }, hobbies: ['music', 'dance', 'movie'] }) console.log('person', person); //2.定义函数 const updateInfo = () => { person = { name: '疯驴子', age: 25, friend: { name: '高启强', age: '28' }, hobbies: ['music', 'dance', 'movie'] } console.log('person', person); } //3.将相关属性,函数,暴露给外界方便使用 return { person, updateInfo } } } </script>
效果如下:

从上述效果图我们可以看出,使用reactive定义的数据会转成响应式对象(proxy)。但是如果直接修改这个对象响应式是会失效的,即使数据内容变量,视图也不会更新。如果修改对象的属性,那么视图是会及时更新的。
效果如下:

如果修改对象的属性,那么视图是会及时更新的。

响应式会失效的情况
像上述对对象直接赋值,响应式是会生效的。除了直接赋值之外,响应式还会生效有以下几种情况:
⏰ 重新赋值
上述针对复杂类型的数据,如果重新赋值的话,相当于是将变量的引用指向了另外一个地址,而这个地址对象是新加的,没有通过reactive进行代理,所以不具有响应式。
针对上述情况,可以通过以下方法使其继续变成响应式数据。
给对象添加一个属性
<template> <div>姓名:{{ person.data.name }}</div><br> <div>年龄:{{ person.data.age }}</div><br> <div>朋友:{{ person.data.friend.name }} - {{ person.data.friend.age }}</div><br> <div v-for="(item, index) in person.data.hobbies" :key="index"> <div>{{ item }}</div> </div><br> <button @click="updateInfo">修改信息</button> </template> <script lang="ts"> //👀:需要什么导入什么 import { reactive } from 'vue' export default { name: 'App', //setup函数是组合式API的入口函数,调用在beforeCreated之前 setup() { //1.定义响应式变量 let person = reactive({ data: { name: '艾薇儿', age: 18, friend: { name: '安妮.海瑟薇', age: '28' }, hobbies: ['music', 'dance', 'movie'] } }) console.log('person', person); //2.定义函数 const updateInfo = () => { person.data = { name: '疯驴子', age: 25, friend: { name: '高启强', age: '28' }, hobbies: ['music', 'dance', 'movie'] } console.log('person', person); } //3.将相关属性,函数,暴露给外界方便使用 return { person, updateInfo } } } </script>
效果如下:

修改之后效果如下:

使用Object.assign()
⏰ 解构
<template> <div>姓名:{{ name }}</div><br> <div>年龄:{{ age }}</div><br> <div>朋友:{{ friend.name }} - {{ person.friend.age }}</div><br> <div v-for="(item, index) in person.hobbies" :key="index"> <div>{{ item }}</div> </div><br> <button @click="updateInfo">修改信息</button> </template> <script lang="ts"> //👀:需要什么导入什么 import { reactive } from 'vue' export default { name: 'App', //setup函数是组合式API的入口函数,调用在beforeCreated之前 setup() { //1.定义响应式变量 let person = reactive({ name: '艾薇儿', age: 18, friend: { name: '安妮.海瑟薇', age: '28' }, hobbies: ['music', 'dance', 'movie'] }) const { name, age, friend, hobbies } = person; console.log('person', person); //2.定义函数 const updateInfo = () => { person.name = '疯驴子' console.log('person', person); } //3.将相关属性,函数,暴露给外界方便使用 return { person, updateInfo, name, age, friend, hobbies } } } </script>
效果如下:

从上述效果图中可以看出解构赋值后失去了响应式。解构赋值中对于基本数据类型是按值传递,对于引用类型是按引用传递。name虽然是person.name的值,但是访问name的时候绕过了对象的get方法,因此失去了响应式,如果是按引用类型来传递的话就不会失去响应式。
使用场景
1. 用来定义复杂数据类型
2. 定义数组的时候需要
浙公网安备 33010602011771号