When using Vue 3's Composition API, I've noticed that inside a template refs behave differently when they are accessed as the property of an object. I think this is best summarized by this example in the SFC Playground, but here's the key code (from a Single File Component):
<script>
import { ref } from 'vue';
export default {
setup() {
const wut = ref(false);
const obj = { wut };
return {
wut,
obj,
};
},
};
</script>
<template>
<!-- obj.wut - false -->
<h3>obj.wut - {{ obj.wut }}</h3>
<!-- !!obj.wut - true -->
<h3>!!obj.wut - {{ !!obj.wut }}</h3>
<!-- obj.wut.value - false -->
<h3>obj.wut.value - {{ obj.wut.value }}</h3>
<!-- !!obj.wut.value - false -->
<h3>!!obj.wut.value - {{ !!obj.wut.value }}</h3>
<!-- does display -->
<h3 v-if="obj.wut">display logic for this: v-if="obj.wut"</h3>
<!-- does not display -->
<h3 v-if="!obj.wut">display logic for this: v-if="!obj.wut"</h3>
<!-- typeof obj.wut - object -->
<h3>typeof obj.wut - {{ typeof obj.wut }}</h3>
</template>
Can anybody explain why it appears to treat the ref as an object in some cases and interpret its value in other cases? Is this a bug, or by design?
Short Answer: this is by design.
Long answer:
Please check Vue3 Guide -> Advanced Guides -> Reactivity -> Reactivity Fundamentals -> Ref unwrapping
Ref Unwrapping
When a ref is returned as a property on the render context (the object returned from setup()) and accessed in the template, it automatically shallow unwraps the inner value. Only the nested ref will require
.value
in the template:
In your example template, the obj.wut
is a ref object, the wut
is an unwrapped primitive value (a Boolean)
Extras:
obj.wut
is rendered as false
in the page, seems it is working without .value
. That is because of a toDisplayString
function in vue, it takes the ref object (obj.wut
), it does JSON.stringify
on the inner value of the ref object. If the value of wut
is a string
(const wut = ref('a string');
), you will see extra double quotes around it in the rendered page, like "a string"
reactive
(const obj = reactive({ wut })
) to access the unwrapped value in the template.