shallowReactive和shallowRef

3,725 阅读1分钟

reactive用来包装一个对象,使其每个对象属性都具有响应性,但是这个包装过程是递归调用的,如果包装的对象有过多属性而又不需要设置相应,无疑是性能浪费

针对这种情况vue设置了shallowReactive shallowRef两个方法来包装响应式数据,通过该方法包装的数据只有第一层具有响应性

shallowReactive

reactive一样,该方法只能把对象或数组包装为响应式对象

<template>
    <div class="about">
        {{ test }}
        <button @click="change">change</button>
    </div>
</template>
<script setup>
const test = shallowReactive({
    a: {
        b: "b",
    },
});

function change() {
    test.a.b = "new";
    console.log(test);
}
</script>

通过change方法改变了test的深层属性,这时会发现控制台中打印的数据是改变后的,而浏览器视图中仍然是原来的对象,而如果把change改成修改test的第一层属性,则会触发视图的更新

function change() {
    test.a = "new";
    console.log(test);
}

shallowRef

该方法就可以包装对象和基础类型的数据了,不过包装基础属性的数据和普通的ref没有区别,这里就只说说包装对象时的用法

<template>
    <div class="about">
        {{ test }}
        <button @click="change">change</button>
    </div>
</template>
<script setup>
const test = shallowRef({
    a: "a",
});

function change() {
    test.value.a = "new";
    console.log(test.value);
}
</script>

shallowReactive不同,这里修改了对象的第一层属性不会触发视图更新,shallowRef的第一层数据实际指的是包装的整个数据,所以改成这样

function change() {
    test.value = { b: "b" };
    console.log(test.value);
}

vue就会响应数据的更新了

triggerRef

shallowRef数据被改变后如果要同步到视图上,可以调用一次triggerRef函数,该函数接收shallowRef数据,并会把该数据同步到视图上

const test = shallowRef({
    a: "A",
    b: "B",
});

function change() {
    test.value.a = "new";
    triggerRef(test);
    test.value.b = "new";
}

通过调用一次该方法,两个数据都会被同步

使用

可以在通过ref获得dom元素时使用来去掉不必要的监听,节省性能