Пропсы только для чтения
Пропсы идут в одну сторону: от родителя вниз, к компоненту. Компонент их читает, но менять не должен. Допустим, у каждого пункта меню появляется кнопка для большой чашки, которая стоит на €1 дороже:
<script setup>
const props = defineProps({
name: { type: String, required: true },
price: { type: Number, required: true },
});
function makeLarge() {
props.price = props.price + 1;
}
</script>
<template>
<li class="item">
<span>{{ name }}</span>
<span class="price">€{{ price }}</span>
<button @click="makeLarge">Большая</button>
</li>
</template>defineProps возвращает пропсы в объекте, здесь он сохранён как props, для скрипта. (В шаблоне цена по-прежнему просто price.) Но нажатие на кнопку цену не меняет, а консоль пишет:
[Vue warn]: Set operation on key "price" failed: target is readonly.Пропсы доступны только для чтения: их можно читать, но нельзя менять. Цена принадлежит родителю, который может передавать её и другим компонентам. Если бы каждый компонент мог её менять, разные части страницы показывали бы разные цены, и никто не понял бы, какая из них верная. (В следующем уроке вы увидите, как компонент просит родителя изменить данные родителя.)
Большая ли именно эта чашка — дело самого компонента, а не родителя. Это собственное состояние компонента: ref в его <script setup>, как в App.vue:
const large = ref(false);И у каждого <MenuItem /> оно своё. Каждый пункт на странице — отдельная копия компонента со своими переменными, поэтому большой эспрессо не делает большим чай. Цена, которую показывает пункт, тогда может быть вычисляемым значением, составленным из пропа и состояния компонента.
Задание
- 1
Нажмите «Большая»: цена остаётся прежней, а в консоли появляется предупреждение. Исправьте это: заведите в
MenuItemрефlarge, сначалаfalse, которыйmakeLargeделаетtrue. Покажите вычисляемое значениеshownPriceвместоprice: цена плюс €1, когда пункт большой, и цена без изменений в остальных случаях. - 2
Пусть покупатель сможет передумать: переименуйте
makeLargeвtoggleSize, которая переключаетlargeсfalseнаtrueи обратно. Когда пункт большой, на кнопке написаноОбычнаявместоБольшая.