Здравствуйте.
Есть, к примеру,
такой массив[
{
"id": 0,
"title": "Задача №1",
"description": "Описание задачи",
"variants": [
{
"variantId": 0,
"text": "Текст первого варианта",
"isMarked": true
},
{
"variantId": 1,
"text": "Текст второго варианта",
"isMarked": false
}
]
},
{
"id": 1,
"title": "Задача №2",
"description": "Описание задачи",
"variants": [
{
"variantId": 0,
"text": "Текст первого варианта",
"isMarked": true
},
{
"variantId": 1,
"text": "Текст второго варианта",
"isMarked": true
},
{
"variantId": 2,
"text": "Текст третьего варианта",
"isMarked": true
}
]
},
{
"id": 2,
"title": "Задача №3",
"description": "Описание задачи",
"variants": [
{
"variantId": 0,
"text": "Текст первого варианта",
"isMarked": false
},
{
"variantId": 1,
"text": "Текст второго варианта",
"isMarked": false
},
{
"variantId": 2,
"text": "Текст третьего варианта",
"isMarked": false
},
{
"variantId": 3,
"text": "Текст четвертого варианта",
"isMarked": true
}
]
}
]
Он олицетворяет собой список задач и варианты их решений. Требуется сделать так, чтобы некоторые варианты решения
isMarked
можно было менять на противоположные.
Я сделал примерно такую структуру компонентов во Vue:
// index.vue
<template>
<div class="task-list">
<Task v-for="data in tasks" :key="data.id" :data="data" />
</div>
</template>
<script>
// ...
data() {
return {
tasks: [/* массив из примера выше*/]
}
}
</script>
// Task.vue
<template>
<div>
<h1>{{ data.title }}</h1>
<p>{{ data.description }}</p>
<ValiantsList :variants="data.variants" />
</div>
</template>
<script>
// ...
props: {
data: {
type: Object,
required: true,
}
}
</script>
// variantsList.vue
<template>
<div>
<Variant v-for="variant in variants" :key="variant.id" :variant="variant" />
</div>
</template>
// variant.vue
<template>
<div>
<p>{{ variant.text }}</p>
<span @click="toggleMark">{{ markLabel }}</span>
</div>
</template>
<script>
// ...
computed: {
markLabel() {
return variant.isMarked ? 'Снять отметку' : 'Поставить отметку'
}
},
methods: {
toggleMark() {
// ???
}
}
</script>
Этот объект я могу хранить во Vuex, к примеру. И дополнительно надо будет отослать запрос к API со сменой пометки isMark конкретного варианта для конкретного вопроса.
Проблема в том, что я не знаю как лучше передать информацию для изменения состояния во Vuex и к API
isMarked
кликнутого варианта. Если бы значения
variantId
были бы уникальными для любых вопросов, тогда, в случае с Vuex можно бы было выкрутиться: искать по всем задачам и в них по всем вариантам ответов, с каким variantId совпал, у того и поменять isMarked. Но в данном примере так не получится, потому что тут не хватает id от самой задачи, для облегчения поиска во Vuex.
Какие варианты я вижу:
- Пробрасывать к каждому variants дополнительно id самой задачи, например, в отдельном props'е. Но это нужно плодить пропсы и если variants будут глубоко вложены, то в каждый промежуточный компонент от задачи до вариантов надо вставлять это дополнительное поле с id задачи
- Еще напрашивается сделать просто emit в variant и поймать его в task, но variant может быть вложен глубоко и опять надо будет пробрасывать через все промежуточные компоненты
- В самом variant вызывать action на изменение состояния. Но чтобы это вызвать и найти на какой задаче менять isMarked требуется id задачи, а ее тогда опять получается, что нужно пробрасывать от родителя до самого конца всех потенциально промежуточных компонентов к variant
- Воспользоваться Event Bus, но этот вариант не очень приветствуется в современных подходах, да и не играет на руку с модульностью компонентов добавляя связанности
- В самом начале, в task изначально сделать map всем вариантам решения задачи и прописать туда что-то вроде
taskId
, чтобы не протаскивать его отдельным свойством через вложенные компоненты, но это как-то так себе
Это облегченный пример, тут, конечно, напрашивается избавиться от
variantsList
и эмитить событие из
variant
ловя его в
task
. Но промежуточных компонентов может быть много.
Подскажите, пожалуйста, как лучше с этим быть?