У меня есть структура данных с вложенными объектами, которую я хочу связать с подкомпонентами, и я хотел бы, чтобы эти компоненты редактировали структуру данных напрямую, чтобы я мог сохранить все это из одного места. Структура что-то вроде
job = {
id: 1,
uuid: 'a-unique-value',
content_blocks: [
{
id: 5,
uuid: 'some-unique-value',
block_type: 'text',
body: { en: { content: 'Hello' }, fr: { content: 'Bonjour' } }
},
{
id: 9,
uuid: 'some-other-unique-value',
block_type: 'text',
body: { en: { content: 'How are you?' }, fr: { content: 'Comment ça va?' } }
},
]
}
Итак, я создаю экземпляры своих субкомпонентов вот так
<div v-for="block in job.content_blocks" :key="block.uuid">
<component :data="block" :is="contentTypeToComponentName(block.block_type)" />
</div>
(contentTypeToComponentName
идет от text
до TextContentBlock
, то есть имени компонента)
TextContentBlock
выглядит так
export default {
props: {
data: {
type: Object,
required: true
}
},
created: function() {
if (!this.data.body) {
this.data.body = {
it: { content: "" },
en: { content: "" }
}
}
}
}
Функция created()
заботится о добавлении отсутствующих специфичных для блока данных, которые неизвестны компоненту, добавляющему новый content_blocks
, для случаев, когда я хочу динамически добавлять блоки с помощью специальной кнопки, которая выглядит следующим образом
addBlock: function(block_type) {
this.job.content_blocks = [...this.job.content_blocks, {
block_type: block_type,
uuid: magic_uuidv4_generator(),
order: this.job.content_blocks.length === 0 ? 1 : _.last(this.job.content_blocks).order + 1
}]
}
Шаблон для TextContentBlock
это
<b-tab v-for="l in ['fr', 'en']" :key="`${data.uuid}-${l}`">
<template slot="title">
{{ l.toUpperCase() }} <span class="missing" v-show="!data.body[l] || data.body[l] == ''">(missing)</span>
</template>
<b-form-textarea v-model="data.body[l].content" rows="6" />
<div class="small mt-3">
<code>{{ { block_type: data.block_type, uuid: data.uuid, order: data.order } }}</code>
</div>
</b-tab>
Теперь, когда я загружаю данные из API, я могу правильно редактировать и сохранять содержимое этих блоков - что странно, учитывая, что реквизит должен быть неизменным.
Однако, когда я добавляю новые блоки, textarea
выше не позволит мне что-либо редактировать. Я ввожу в него материал, и он просто удаляет его (или, я думаю, он заменяет его «предыдущим» или «начальным» значением). Этого не происходит при извлечении контента из API (скажем, при загрузке страницы).
Во всяком случае, это привело меня к открытию неизменности, затем я создал локальную копию data
реквизита, как это
data: function() {
return {
block_data: this.data
}
}
и каждый data
корректируется до block_data
, но я получаю то же поведение, что и раньше.
Что именно мне не хватает?