vue3定义响应式数据之toRaw和markRaw

1,826 阅读1分钟

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

toRaw和markRaw用来处理响应式对象和普通对象之间的转换的,其中toRaw是将响应式对象转成普通的原生对象,而markRaw是直接定义一个普通的原生对象,并且这个对象永远不能被转成响应式。

toRaw

toRaw是返回reactive或readonly proxy的原始对象。也就是说将一个由reactive生成的响应式对象转为普通对象。这是一个转义口,可用于临时读取而不会引起 proxy 访问/跟踪开销,也可用于写入而不会触发更改。

toRaw的用法

<template>
  <div class="hello">
    <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>
  </div>
</template>

<script setup>
import { reactive, toRaw } from 'vue';
let person = {
  name: '艾薇儿',
  age: 18,
  friend: {
    name: '安妮·海瑟薇',
    age: '28'
  },
  hobbies: ['music', 'dance', 'movie']
};
const reactivePerson = reactive(person);
console.log('person', person);
console.log('reactivePerson', reactivePerson);
console.log(toRaw(reactivePerson) === person);

const updateInfo = () => {
  person.friend.name = '疯驴子';
  console.log('person', person);
  console.log('reactivePerson', reactivePerson);
}
</script>

效果如下:

image.png

修改之后的效果如下:

image.png 此时toRaw(reactivePerson)就是个普通对象,只是这个对象是通过响应式对象转过来的。

toRaw的使用场景

用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。

markRaw

标记一个对象,使其永远不会转换为proxy。返回对象本身。

markRaw的用法

<template>
  <div class="hello">
    <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>
  </div>
</template>

<script setup>
import { markRaw, reactive, isReactive } from 'vue';
let person = markRaw({
  name: '艾薇儿',
  age: 18,
  friend: {
    name: '安妮·海瑟薇',
    age: '28'
  },
  hobbies: ['music', 'dance', 'movie']
});
console.log('person', person);
console.log('isReactive', isReactive(reactive(person)));

const updateInfo = () => {
  person.friend.name = '疯驴子';
  console.log('person', person);
}
</script>

初始效果:

image.png

修改数据之后效果:

image.png 此时person就相当于是一个普通对象,而且这个对象永远不能转成响应式对象。

markRaw的应用场景

  1. 有些值不应被设置为响应式的,如第三方库,组件等
  2. 当渲染具有不可变数据源的大列表时,可以不使用响应性,从而提高性能