vue3定义响应式数据之shallowReactive和shadowRef

3,944 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第12天,点击查看活动详情

前面我们介绍过ref和reactive,toRef和toRefs。说白了toRef和toRefs可以看成是浅拷贝reactive对象的,那么我们这篇要介绍的shallowReactive和shallowRef就是浅层的reactive和ref。

回顾ref和reactive的区别

ref和reactive的区别就是:

类别refreactive
返回数据类型RefImpl对象(也叫ref对象)Proxy对象
传入基本类型返回{value: 基本类型}禁止这么做
传入引用类型返回{value: Proxy对象}Proxy对象

也就是说ref可以处理基本类型和引用类型,对于引用类型而言,内部是Proxy对象,可以深度监听对象的属性,实现响应式。对于reactive来说,它只能处理引用类型,转成Proxy对象,可以深度监听对象的属性,实现响应式。

shallowReactive和shallowRef

shallowReactive和shadowRef就是浅层的reactive和ref。可以理解成,shallowReactive只能处理引用类型,只能监听对象的最外层属性,如果深度属性发生改变,是监听不到的,没法实现响应式。shallowRef和ref不同,只能处理基本类型,不能处理引用类型。处理基本类型的时候和ref一样。

shallowReactive的用法

<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>
<script setup>
import { shallowReactive } from 'vue';
let person = shallowReactive({
  name: '艾薇儿',
  age: 18,
  friend: {
    name: '安妮·海瑟薇',
    age: '28'
  },
  hobbies: ['music', 'dance', 'movie']
});
console.log('person', person);
const updateInfo = () => {
  person.friend.name = '疯驴子';
  console.log('person', person);
}
</script>

初始化效果:

image.png

修改之后效果:

image.png 数据发生改变,但是视图没有更新

shallowReactive的使用场景

只需要监听对象最外层属性的变化,可以提高性能。

shallowRef的用法

<div>姓名:{{name}}</div>
<button @click="updateInfo">修改信息</button>

import { shallowReactive, shallowRef } from 'vue';
const name = shallowRef('高启强');
console.log('name', name);
const updateInfo = () => {
  name.value = '安欣';
  console.log('name', name);
}

初始效果:

image.png

修改之后效果:

image.png

shallowRef的场景

定义基本类型,可以提高性能

shallowReadonly

shallowReadonly创建一个 proxy,使其自身的 property 为只读,但不执行嵌套对象的深度只读转换 (暴露原始值)。

shallowReadonly的用法

import { shallowRef, shallowReadonly } from 'vue';
let person = shallowReadonly({
  name: '艾薇儿',
  age: 18,
  friend: {
    name: '安妮·海瑟薇',
    age: '28'
  },
  hobbies: ['music', 'dance', 'movie']
});
console.log('person', person);
person.name = '高启强';

效果如下:

image.png 对象的第一层属性是不能修改的,只能读

person.friend.name = '高启强';

效果如下:

image.png 对象的深层次属性依然可读可写