I am new to vue3 and have some confusion about shallowReactive.
only root-level properties are reactive for a shallow reactive object.
But when I click the add button, the value of count2 will still change:
<script setup>
import { shallowReactive } from 'vue'
const test = shallowReactive({
count1: 0,
nested: {
count2: 0
}
})
const add = () => {
test.count1
test.nested.count2
}
</script>
<template>
<button @click="add"> </button>
<div>{{ test.count1 }}</div>
<div>{{ test.nested.count2 }}</div>
</template>
CodePudding user response:
When you modify something nested inside a shallowReactive
it doesn't mean the mutation is not performed. It only means Vue is not told: you need to check for differences between M (model) and V (view/template/DOM) now.
Because you're also changing test.count1
in the same function, which is watched, the component gets diff-ed. The diff-ing doesn't care what's reactive. It only looks for differences between M and V. If it finds any, it updates them.
Let's make separate functions for nested and non-nested props. As you can see, V only updates when the non-nested prop is changed. At that point, the entire view (template) is checked and updated according to model:
const { createApp, shallowReactive } = Vue;
createApp({
setup() {
const test = shallowReactive({
count1: 0,
nested: {
count2: 0
}
})
const add = () => {
test.count1
}
const addWithoutUpdate = () => {
test.nested.count2 ;
}
return { test, add, addWithoutUpdate }
}
}).mount('#app')
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.2.37/vue.global.prod.min.js"></script>
<div id="app">
<button @click="add"> </button>
<button @click="addWithoutUpdate">Only add to nested</button>
<div>{{ test.count1 }}</div>
<div>{{ test.nested.count2 }}</div>
</div>
In other words, shallowReactive
doesn't freeze the nested objects. They can be mutated. But Vue will only diff the template when something it actually watches changes. Could be the top level of this shallow reference or some other, completely unrelated reactive variable.