Vue3中 响应式 API ( readonly、shallowReadonly、toRaw、markRaw ) 详解

简介: Vue3中 响应式 API ( readonly、shallowReadonly、toRaw、markRaw ) 详解

传送门:Vue3中 响应式 API ( reactive、ref、toRef、toRefs ) 详解

传送门:Vue3中 响应式 API( shallowReactive、shallowRef、triggerRef 、customRef )详解

1. readonly 函数

接受一个对象 (不论是响应式还是普通的) 或是一个 ref,返回一个原值的只读代理。

只读代理是深层的:对任何嵌套属性的访问都将是只读的。它的 ref 解包行为与 reactive() 相同,但解包得到的值是只读的。

要避免深层级的转换行为,请使用 shallowReadonly() 作替代。

<template>
  <div>
    <div>
      {{count}}
      <button @click="changeCount">changeCount</button>
    </div>
    <div>
      {{obj1.name}} {{obj1.info.age}}
      <button @click="obj1Age">obj1Age</button>
    </div>
  </div>
</template>
<script>
import { reactive,readonly, ref } from 'vue';
export default {
  setup(){
    let count = ref(0);
    let obj1 = reactive({
      name:'张三',
      info:{
        age:18
      }
    })
    count = readonly(count);
    obj1 = readonly(obj1);
    const changeCount = () => {
      count.value++;
      console.log(count)
    }
    const obj1Age = () => {
      obj1.name = '李四';
      obj1.info.age++;
      console.log(obj1)
    }
    return {
      count,
      changeCount,
      obj1,
      obj1Age,
    }
  } 
}
</script>

分别触发 changeCount、obj1Age 一次

1ecd1b2606ed46e9956a89f231c9802c.png

2. shallowReadonly 函数

readonly() 的浅层作用形式

和 readonly() 不同,这里没有深层级的转换:只有根层级的属性变为了只读。属性的值都会被原样存储和暴露,这也意味着值为 ref 的属性不会被自动解包了。

1ecd1b2606ed46e9956a89f231c9802c.png

<template>
  <div>
    <div>
      {{count}}
      <button @click="changeCount">changeCount</button>
    </div>
    <div>
      {{obj1.name}} {{obj1.info.age}}
      <button @click="obj1Age">obj1Age</button>
    </div>
  </div>
</template>
<script>
import { reactive,shallowReadonly, ref } from 'vue';
export default {
  setup(){
    let count = ref(0);
    let obj1 = reactive({
      name:'张三',
      info:{
        age:18
      }
    })
    count = shallowReadonly(count);
    obj1 = shallowReadonly(obj1);
    const changeCount = () => {
      count.value++;
      console.log(count)
    }
    const obj1Age = () => {
      obj1.name = '李四';
      obj1.info.age++;
      console.log(obj1)
    }
    return {
      count,
      changeCount,
      obj1,
      obj1Age,
    }
  } 
}
</script>

分别触发 changeCount、obj1Age 一次

1ecd1b2606ed46e9956a89f231c9802c.png

3. toRaw 函数

根据一个 Vue 创建的代理返回其原始对象。

toRaw() 可以返回由 reactive()、readonly()、shallowReactive() 或者 shallowReadonly() 创建的代理对应的原始对象。

这是一个可以用于临时读取而不引起代理访问/跟踪开销,或是写入而不触发更改的特殊方法。不建议保存对原始对象的持久引用,请谨慎使用。

<template>
  <div>
    <div>
      {{obj.name}} {{obj.info.age}}
      <button @click="objToRaw">objToRaw</button>
    </div>
  </div>
</template>
<script>
import { reactive,toRaw } from 'vue';
export default {
  setup(){
    let obj = reactive({
      name:'张三',
      info:{
        age:18
      }
    })
    const objToRaw = () => {
      let objRaw = toRaw(obj)
      objRaw.info.age++
      console.log(obj,objRaw)
    }
    return {
      obj,
      objToRaw,
    }
  } 
}
</script>

触发 objToRaw 两次

1ecd1b2606ed46e9956a89f231c9802c.png

4. markRaw 函数

将一个对象标记为不可被转为代理。返回该对象本身。

作用:标记一个对象,使其永远不会再成为响应式对象;

应用场景:

  • 有些值不应被设置为响应式的,如:复杂的第三方类库等;
  • 当渲染具有不可变数据源的大列表时,跳过响应式转换可提高性能;

1ecd1b2606ed46e9956a89f231c9802c.png

<template>
  <div>
    <div>姓名:{{obj.name}} </div> 
    <div>年龄:{{obj.info.age}} </div> 
    <div v-if="obj.car">座驾:{{obj.car}} </div> 
    <div v-if="obj.address">地址:{{obj.address}} </div> 
    <button @click="updateObj">updateObj</button>
    <button @click="changeAddress">changeAddress</button>
    <button @click="changeCar">changeCar</button>
  </div>
</template>
<script>
import { reactive,markRaw } from 'vue';
export default {
  setup(){
    let obj = reactive({
      name:'张三',
      info:{
        age:18
      }
    })
    const updateObj = () => {
      const address = { province:'湖北',city:'武汉' };
      obj.address = address; // obj 配置了 Proxy 代理,因此捕获到对 obj 任何属性的操作且都是响应式的;
      const car = { brand:'宝马',price:30 };
      obj.car = markRaw(car); // car内部属性值已经改了,只是没有响应式更新。它和readonly不同,readonly是压根不让修改 
    }
    function changeAddress(){
      obj.address.province = '江苏';
      obj.address.city = '南京';
      console.log(obj) 
    }
    function changeCar(){
      obj.car.brand = 'BMW',
      obj.car.price+= 1
      console.log(obj)
    };
    return {
      obj,
      updateObj,
      changeCar,
      changeAddress,
    }
  } 
}
</script>

依次触发 updateObj、changeAddress、changeCar 一次,效果如下:

(若先触发 changeCar 再触发 changeAddress ,car 的页面信息会进行更新,因为 address 的改变带动了页面的更新 )

1ecd1b2606ed46e9956a89f231c9802c.png



相关文章
|
17天前
|
JavaScript 前端开发 API
Vue 3新特性详解:Composition API的威力
【10月更文挑战第25天】Vue 3 引入的 Composition API 是一组用于组织和复用组件逻辑的新 API。相比 Options API,它提供了更灵活的结构,便于逻辑复用和代码组织,特别适合复杂组件。本文将探讨 Composition API 的优势,并通过示例代码展示其基本用法,帮助开发者更好地理解和应用这一强大工具。
21 1
|
21天前
|
API
vue3知识点:响应式数据的判断
vue3知识点:响应式数据的判断
27 3
|
25天前
|
缓存 JavaScript UED
优化Vue的响应式性能
【10月更文挑战第13天】优化 Vue 的响应式性能是一个持续的过程,需要不断地探索和实践,以适应不断变化的应用需求和性能挑战。
30 2
|
29天前
|
JavaScript 前端开发
Vue 2 和 Vue 3 之间响应式区别
10月更文挑战第7天
32 2
|
1月前
|
缓存 JavaScript API
Vue 3的全新Reactivity API:解锁响应式编程的力量
Vue 3引入了基于Proxy的全新响应式系统,提升了性能并带来了更强大的API。本文通过示例详细介绍了`reactive`、`ref`、`computed`、`watch`等核心API的使用方法,帮助开发者深入理解Vue 3的响应式编程。无论你是初学者还是资深开发者,都能从中受益,构建更高效的应用程序。
19 1
|
1月前
|
缓存 JavaScript 前端开发
深入理解 Vue 3 的 Composition API 与新特性
本文详细探讨了 Vue 3 中的 Composition API,包括 setup 函数的使用、响应式数据管理(ref、reactive、toRefs 和 toRef)、侦听器(watch 和 watchEffect)以及计算属性(computed)。我们还介绍了自定义 Hooks 的创建与使用,分析了 Vue 2 与 Vue 3 在响应式系统上的重要区别,并概述了组件生命周期钩子、Fragments、Teleport 和 Suspense 等新特性。通过这些内容,读者将能更深入地理解 Vue 3 的设计理念及其在构建现代前端应用中的优势。
31 0
深入理解 Vue 3 的 Composition API 与新特性
|
1月前
|
JavaScript 前端开发 网络架构
如何使用Vue.js构建响应式Web应用
【10月更文挑战第9天】如何使用Vue.js构建响应式Web应用
|
21天前
|
JavaScript 前端开发 API
vue3知识点:Vue3.0中的响应式原理和 vue2.x的响应式
vue3知识点:Vue3.0中的响应式原理和 vue2.x的响应式
23 0
|
22天前
|
API
《vue3第四章》Composition API 的优势,包含Options API 存在的问题、Composition API 的优势
《vue3第四章》Composition API 的优势,包含Options API 存在的问题、Composition API 的优势
25 0
|
22天前
|
JavaScript 前端开发 API
《vue3第六章》其他,包含:全局API的转移、其他改变
《vue3第六章》其他,包含:全局API的转移、其他改变
20 0

热门文章

最新文章