渐层响应式shallowRef和shallowReactive

渐层响应式shallowRef和shallowReactive

在vue3中,响应式系统可以让我们轻松的追踪到数据的变化。通常我们会使用ref和reactive来定义响应式数据;这两个API都是深度的,ref用来定义基本类型和对象类型的响应式数据,而reactive是用来定义对象类型的响应式数据的;如果因为性能原因我们并不想追踪很深的响应式的,这个时候我们就需要使用shallowRef和shallowReactive来对数据进行渐层的处理

1. 回顾ref和reactive

vue 复制代码
<template>
  <h2>ref姓名:{{ deepRef.user.name }}</h2>
  <h2>ref年龄:{{ deepRef.user.age }}</h2>
  <h2>reactive姓名:{{ deepReactive.user.name }}</h2>
  <h2>reactive姓名:{{ deepReactive.user.age }}</h2>
  <button @click="ChangeName">修改姓名</button>
  <button @click="ChangeAge">修改年龄</button>
</template>
<script setup>
import { ref, reactive } from 'vue'
const deepRef = ref({ user: { name: 'Alice', age: 20 } })
const deepReactive = reactive({ user: { name: 'Bob', age: 25 } })
function ChangeName() {
  deepRef.value.user.name = '张三'
}

function ChangeAge() {
  deepReactive.user.age += 1
}

</script>

这样修改数据没有一点问题

2.shallowRef

  • 如果更改成shallowRef则不会起作用
vue 复制代码
const deepRef = shallowRef({ user: { name: 'Alice', age: 20 } })

这样点击并不会其任何作用,因为shallowRef只跟踪到deepRef.value,至于deepRef.value.user并不会被它追踪到,那么shallowRef到底有什么作用呢?

什么时候使用shallowRef?

当你有一个大型的、嵌套非常深的对象且你只需关心这个对象整体有没有被替换,不关心内部到底那里更换了,使用它可以消除很深的性能开销;常于markRaw配合使用,跳过某些大对象的响应式转换,例如

  • 比如我们有一个配置文件,这个配置文件类似json一样有一大堆数据,我们并不需要修改数据中某一项,只要修改就是整体替换,避免修改某一项导致配置文件失效出错
vue 复制代码
<template>
  <div>
    <pre>{{ config }}</pre>
    <button @click="updateConfig">更新配置</button>
  </div>
</template>
<script setup>
import { shallowRef } from 'vue';
const config = shallowRef({
  theme: 'dark',
  layout: {
    header: true,
    footer: false
  }
})

function updateConfig() {
  // 整体替换,触发更新
  config.value = {
    ...config.value,
    theme: 'light',
    layout: { header: false, footer: true }
  }
}

</script>
<style></style>

3.shallowReactive

这个也是类似shallowRef,当时响应式对象里面还有一个对象,里面的对象就并不能深度追踪到了

vue 复制代码
<template>
  <div>
    <p>计数:{{ state.count }}</p>
    <p>用户:{{ state.user.name }}</p>
    <button @click="increment">增加 count</button>
    <button @click="changeUserName">修改用户名</button>
  </div>
</template>
<script setup>
import { shallowReactive } from 'vue';
const state = shallowReactive({
  count: 0,
  user: { name: 'Alice' }   // user 不是响应式的
})
function increment() {
  state.count++   // 会触发更新
}

function changeUserName() {
  state.user.name = 'Bob'   // 不会触发更新,界面上的用户名不会改变
  // 但如果想要更新,可以整体替换 user 对象:
  // state.user = { name: 'Bob' }   // 这会触发更新,因为替换了顶层属性
}
</script>

什么时候使用shallowReactive?

比如你有一个对象,只希望顶层是响应式的,而内部嵌套不需要被追踪时;例如一个表单对象,里面包含了和上面一样含有复杂的配置对象,这个配置永远都不需要变动,或者它只是只读的;、

实际使用中我们可以使用markRaw来标记某个对象永远都不会是响应式的

vue 复制代码
import { shallowRef, markRaw } from 'vue'

const hugeObject = markRaw({ /* 巨大的静态数据 */ })
const state = shallowRef(hugeObject)

// 现在 state.value 中的任何属性变化都不会触发响应式更新
// 只有整体替换 state.value 时才会更新
相关推荐
郭老二6 小时前
【前端】vue3:编译步骤
前端
不在逃避q7 小时前
Trae/Vs Code/Cursor命令行无法跑npm命令
前端·arcgis·npm
夏殇之殁7 小时前
包中创建自定义列表项。 . 使用自定义列表项进行数据绑定 . 将天气预报数据保存到本地内存表,通过LiveBindings进行显示。 ...
服务器·前端·javascript
The Chosen One9857 小时前
高进度算法模板速记(待完善)
java·前端·算法
陈随易7 小时前
MoonBit抓包模块pcap,查看电脑的每一次联网通信
前端·后端·程序员
新中地GIS开发老师8 小时前
WebGIS开发学生作品|低空航天管理与航线规划系统
前端·javascript·webgis·三维gis开发
用户059540174468 小时前
大模型对话记忆持久化踩坑实录:用 Playwright 自动化测了 300 次,终于揪出会话丢失的真凶
前端·css
丙氨酸長鏈8 小时前
Web前端入门第 问:JavaScript 一个简单的 IndexedDB 数据库入门示例
前端·javascript·数据库
kyriewen9 小时前
面试官让我手写虚拟列表——AI生成的版本,快速滚动几下就白屏了
前端·javascript·面试
IT_陈寒10 小时前
Vite热更新失效?你可能漏了这个配置
前端·人工智能·后端