@Fedooot01

Как лучше организовать передачу данных во Vue?

Здравствуйте.
Есть, к примеру,
такой массив
[
  {
    "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.

Какие варианты я вижу:
  1. Пробрасывать к каждому variants дополнительно id самой задачи, например, в отдельном props'е. Но это нужно плодить пропсы и если variants будут глубоко вложены, то в каждый промежуточный компонент от задачи до вариантов надо вставлять это дополнительное поле с id задачи
  2. Еще напрашивается сделать просто emit в variant и поймать его в task, но variant может быть вложен глубоко и опять надо будет пробрасывать через все промежуточные компоненты
  3. В самом variant вызывать action на изменение состояния. Но чтобы это вызвать и найти на какой задаче менять isMarked требуется id задачи, а ее тогда опять получается, что нужно пробрасывать от родителя до самого конца всех потенциально промежуточных компонентов к variant
  4. Воспользоваться Event Bus, но этот вариант не очень приветствуется в современных подходах, да и не играет на руку с модульностью компонентов добавляя связанности
  5. В самом начале, в task изначально сделать map всем вариантам решения задачи и прописать туда что-то вроде taskId, чтобы не протаскивать его отдельным свойством через вложенные компоненты, но это как-то так себе


Это облегченный пример, тут, конечно, напрашивается избавиться от variantsList и эмитить событие из variant ловя его в task. Но промежуточных компонентов может быть много.

Подскажите, пожалуйста, как лучше с этим быть?
  • Вопрос задан
  • 165 просмотров
Решения вопроса 1
0xD34F
@0xD34F Куратор тега Vue.js
промежуточных компонентов может быть много

provide / inject
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы