У шаблоні .value писати не треба - але лише для ref верхнього рівня, тобто змінних, оголошених прямо в <script setup> (чи повернених з setup()).
<script setup>
import { ref } from 'vue';
const count = ref(1);
const item = { id: ref(1) }; // ref усередині звичайного об'єкта
</script>
<template>
<p>{{ count + 1 }}</p> <!-- 2 -->
<p>{{ item.id }}</p> <!-- 1 -->
<p>{{ item.id + 1 }}</p> <!-- [object Object]1 -->
</template>
Чому так:
count- ref верхнього рівня, у виразі він розгорнутий;item.id- ref усередині звичайного об'єкта. Виразitem.id + 1додає до об'єкта-ref число;{{ item.id }}без обчислень показує1- це окреме правило: якщо кінцевий результат інтерполяції - ref, текст розгортається. Але для будь-якого виразу з ним - ні.
Як виправити:
const { id } = item; // зробити ref верхнього рівня
або явно {{ item.id.value + 1 }}.
Інші правила розгортання:
- у
reactive()ref, що лежить як властивість, розгортається при доступі:state.count, а неstate.count.value; - у масивах і колекціях (
reactive([ref(1)]),Map) - не розгортається, потрібно.value; - props приходять уже розгорнутими значеннями -
.valueне потрібен.
Практичне правило, що знімає плутанину: не класти ref-и всередину звичайних об'єктів. Або окремі ref-и на верхньому рівні, або один reactive/ref з об'єктом, поля якого - звичайні значення.
Інструменти допомагають: Vue - Official (Volar) у редакторі підсвічує, де .value потрібен, а TypeScript покаже, що item.id + 1 додає Ref<number> до числа.
Докладніше в документації: Особливість розгортання в шаблонах