vue3中shallowReactive对比reactive、shallowRef对比ref以及triggerRef作用

本文对比了Vue中shallowReactive与reactive的使用,shallowReactive用于非递归监听,仅更新首层对象变化;而reactive则递归监听。此外,还介绍了shallowRef与ref的异同,shallowRef只关注value层的变化。最后,解释了triggerRef的作用强制更新视图。

一、shallowReactive对比reactive

  • 使用reactive声明的变量为递归监听,使用shallowReactive声明的变量为非递归监听(通俗的讲就是reactive创建的对象将会被vue内部进行递归监听,可以监听到对象中的对象是否发生了改变从而更新视图,而shallowReactive创建的对象只能监听到首层对象的变化)。
<template>
  <!-- reactive -->
  <div>{{ reactiveState }}</div>
  <button @click="reactiveStateChange">改变reactiveState.b.c</button>

  <!-- shallowReactive -->
  <div>{{ shallowReactiveState }}</div>
  <button @click="shallowReactiveChange">改变shallowReactiveState.b.c</button>
</template>

<script>
import { shallowReactive, reactive } from 'vue'
export default {
  name: 'App',
  setup() {
    const reactiveState = reactive({
      a: 'a',
      b: {
        c: 'c',
        d: {
          e: 'e',
        },
      },
    })
    function reactiveStateChange() {
      reactiveState.b.c = 99999
      console.log(reactiveState, 'reactiveState发生了变化且视图更新了')
    }
    const shallowReactiveState = shallowReactive({
      a: 'a',
      b: {
        c: 'c',
        d: {
          e: 'e',
        },
      },
    })
    function shallowReactiveChange() {
      shallowReactiveState.b.c = 99999
      console.log(shallowReactiveState, 'shallowReactiveState发生了变化但视图未更新')
      // 打开下方这行注释视图将进行更新(因为首层对象发生了改变)
      // shallowReactiveState.a = 99999
    }
    return {
      reactiveState,
      reactiveStateChange,
      shallowReactiveState,
      shallowReactiveChange,
    }
  },
}
</script>

二、shallowRef对比ref

  • ref底层相当于调用了一次reactive,并且使用value包裹了创建的变量。
const state = ref(false)
    等价于
const state = reactive({
    value: false,
})
  • 其中shallowRef为非递归监听,ref为递归监听,与shallowReactive和reactive不同的是shallowRef和ref监听的对象首层是value这一层,只有当value发生改变时shallowRef声明的变量才会在视图上进行更新。
<template>
  <div>{{ shallowRefState }}</div>
  <button @click="shallowRefChange">改变state.b.c</button>
</template>

<script>
import { shallowRef, ref, triggerRef } from 'vue'
export default {
  name: 'App',
  setup() {
    const shallowRefState = shallowRef({
      a: 'a',
      b: {
        c: 'c',
        d: {
          e: 'e',
        },
      },
    })
    function shallowRefChange() {
      shallowRefState.value.b.c = 99999
      console.log(shallowRefState, 'shallowRefChange发生了变化但视图未更新')
      // 打开下方代码视图才会进行更新(原因是shallowRefState首层value发生了改变)
      // shallowRefState.value = {
      //   a: 'a',
      //   b: {
      //     c: '变化的数据',
      //     d: {
      //       e: 'e',
      //     },
      //   },
      // }
    }
    return {
      shallowRefState,
      shallowRefChange,
    }
  },
}
</script>

三、triggerRef的作用

  • 上文第二点我们说到只有当value发生改变时shallowRef声明的变量才会在视图上进行更新,而triggerRef的作用则是手动执行与 shallowRef 关联的任何副作用,强制更新视图。
<template>
  <div>{{ shallowRefState }}</div>
  <button @click="shallowRefChange">改变state.b.c</button>
</template>

<script>
import { shallowRef, ref, triggerRef } from 'vue'
export default {
  name: 'App',
  setup() {
    const shallowRefState = shallowRef({
      a: 'a',
      b: {
        c: 'c',
        d: {
          e: 'e',
        },
      },
    })
    function shallowRefChange() {
      shallowRefState.value.b.c = 99999
      triggerRef(shallowRefState)
    }
    return {
      shallowRefState,
      shallowRefChange,
    }
  },
}
</script>

四、没有triggerReactive!没有triggerReactive!没有triggerReactive!

<think>首先,用户的问题是:“我想理解Vue3refshallowRef的区别 请问Vue3 ref vs shallowRef difference”。我需要基于提供的引用内容来回答这个问题。引用来自站内内容:[^1], [^2], [^3]。 关键点从引用中提取: - 引用[1]: 提到customRef,但用户问题不是关于customRef的,所以可能不直接相关。但强调了refshallowRef的区别。 - 引用[2]: 解释了RefShallowRef的区别。Ref允许包装任意JavaScript值,提供.value属性来访问值,并在变化时触发重新渲染。ShallowRef是浅层的,只跟踪值本身的变化,而不深入对象内部。 - 引用[3]: 更详细地比较了refshallowRefref创建完整的响应式引用,递归地将对象所有属性变为响应式。shallowRef只使值本身响应式,不处理对象内部属性。优点:ref适合需要完整响应式支持的场景;shallowRef性能更好,因为不追踪内部变化。缺点:ref可能导致性能问题;shallowRef不适合需要内部属性变化的场景。 现在,构建回答的结构: 1. **介绍RefShallowRef**:简要定义两者。 2. **核心区别**:解释响应式处理的深度。 3. **使用场景和优缺点**:基于引用[3],讨论何时使用哪个。 4. **示例**:提供代码示例来展示区别。 5. **相关问题**:根据系统指令,生成相关问题。 系统指令要求: - 行内数学表达式用$...$,但这里没有数学表达式,所以忽略。 - 独立公式用$$...$$,但可能不需要。 - LaTeX语法正确:确保任何公式正确。 - 使用中文回答:整个回答用中文。 - 生成相关问题:在末尾添加相关问题。 - 引用标识:在引用的段落末尾添加[^1], [^2], [^3]。 回答结构: - 清晰、逐步解释。 - 确保真实可靠,基于引用。 最终回答格式: - 回答用户问题。 - 添加相关问题。 相关问题建议:基于主题,如性能影响、使用场景、其他相关API(如reactive)。 相关问题: 1. 在什么情况下应该优先使用shallowRef而不是ref? 2. Vue3中还有哪些响应式API,如reactive,它们与ref/shallowRef的区别是什么? 3. 如何优化大型对象的响应式性能在Vue3中? 回答大纲: 1. **开头**:直接回答问题,总结区别。 2. **详细解释**: - 定义Ref:创建响应式引用,包括对象内部的递归响应式处理。 - 定义ShallowRef:只处理值本身的响应式,不深入对象。 - 比较:使用场景、优缺点。 3. **代码示例**:提供简单代码展示行为差异。 4. **总结**:何时使用哪个。 5. **相关问题**:列出2-3个。 确保自然添加引用标识:当引用特定内容时添加[^1], [^2], [^3]。</think>### Vue3refshallowRef的区别 在Vue3中,`ref`和`shallowRef`都是用于创建响应式引用的API,但它们处理数据的方式有显著差异。核心区别在于**响应式处理的深度**:`ref`会对数据进行深层次的递归响应式转换,而`shallowRef`只进行浅层次的转换,仅跟踪值本身的变化。下面我将逐步解释两者的区别、使用场景和优缺点,帮助您清晰理解。 #### 1. **Ref(深层响应式引用)** - **定义**:`ref`用于包装任意JavaScript值(如基本类型或对象),使其成为响应式数据。它通过`.value`属性访问内部值,并在值变化时自动触发组件重新渲染。关键点是,如果包装的是一个对象,`ref`会递归地将对象的所有属性都转换为响应式,这意味着嵌套对象或数组的内部变化也会被追踪。 - **优点**:适用于需要完整响应式支持的场景,例如当对象结构复杂且需要内部属性变化时自动更新UI。这确保了数据变化的全面响应性[^3]。 - **缺点**:对于大型对象或深层嵌套结构,递归处理可能导致性能开销,因为Vue需要为每个属性设置响应式代理。初始化时也可能消耗更多时间[^3]。 - **示例代码**: ```javascript import { ref } from &#39;vue&#39;; const objRef = ref({ a: 1, b: { c: 2 } }); // 修改内部属性会触发响应式更新 objRef.value.b.c = 3; // 视图自动更新 ``` #### 2. **ShallowRef(浅层响应式引用)** - **定义**:`shallowRef`也只包装值并使其响应式,但它仅跟踪值本身的直接变化(即`.value`的重新赋值),不会递归处理对象内部属性。如果包装的是对象,内部属性的变化不会触发响应式更新,除非整个对象被替换。 - **优点**:性能更优,尤其适合处理大型对象或不需要内部属性追踪的场景(如只关心对象整体替换)。这减少了Vue的依赖追踪开销[^3]。 - **缺点**:不适合需要对象内部属性变化时自动更新的情况。如果内部属性被修改,必须手动触发更新(例如使用`triggerRef`),否则视图不会刷新[^2][^3]。 - **示例代码**: ```javascript import { shallowRef, triggerRef } from &#39;vue&#39;; const objShallowRef = shallowRef({ a: 1, b: { c: 2 } }); // 修改内部属性不会触发更新 objShallowRef.value.b.c = 3; // 视图不更新 // 只有整个对象替换时才触发更新 objShallowRef.value = { a: 4, b: { c: 5 } }; // 视图更新 // 如果需要强制更新内部变化,可手动调用 triggerRef triggerRef(objShallowRef); ``` #### 3. **核心区别总结** - **响应式深度**:`ref`是深层的(递归响应式),`shallowRef`是浅层的(仅顶层响应式)[^2][^3]。 - **性能影响**:`ref`在复杂对象上可能更耗性能,`shallowRef`更高效但需手动处理内部更新。 - **使用场景**: - 使用`ref`:当需要对象内部属性变化自动触发UI更新时,例如表单数据或嵌套状态管理。 - 使用`shallowRef`:当只关心值整体替换(如从API获取新数据对象)或优化大型对象性能时。 #### 4. **注意事项** - 在Vue3中,如果使用`shallowRef`但需要内部属性响应式,可以结合`reactive`(用于对象响应式)或手动调用`triggerRef`[^3]。 - 引用中提到,`customRef`允许自定义get/set逻辑,但`ref`和`shallowRef`是更常用的内置API[^1]。 通过理解这些区别,您可以根据具体需求选择合适的API,以平衡响应式能力和性能。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值