F
F
Fedooot012021-10-18 19:41:11
Vue.js
Fedooot01, 2021-10-18 19:41:11

What is the best way to organize data transfer in Vue?

Hello.
There are, for example,

such an array
[
  {
    "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
      }
    ]
  }
]


It represents a list of tasks and options for their solutions. It is required to make sure that some solutions isMarkedcan be reversed.

I made something like this component structure in 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>


I can store this object in Vuex, for example. And in addition, you will need to send a request to the API with a change in the isMark mark of a specific option for a specific question.

The problem is that I don't know how best to pass the state change information to Vuex and to the isMarkedclicked option API. If the values variantId​​were unique for any questions, then, in the case of Vuex, it would be possible to get out: search in all tasks and in them for all answer options, with which variantId matched, and change isMarked. But in this example, this will not work, because there is not enough id from the task itself, to facilitate searching in Vuex.

What options do I see:
  1. Forward to each variants additionally the id of the task itself, for example, in a separate props. But it is necessary to multiply the props and if the variants are deeply nested, then this additional field with the task id must be inserted into each intermediate component from the task to the variants
  2. It also begs to do just emit in variant and catch it in task, but variant can be nested deeply and again it will be necessary to pass through all intermediate components
  3. In the variant itself, call action on a state change. But in order to call this and find on which task to change isMarked, the task id is required, and then it again turns out that you need to forward from the parent to the very end of all potentially intermediate components to the variant
  4. Use the Event Bus, but this option is not very welcome in modern approaches, and does not play into the hands of the modularity of components by adding connectivity
  5. At the very beginning, in the task, initially make a map for all options for solving the problem and write something like there taskIdso as not to drag it as a separate property through nested components, but this is somehow so-so


This is a lightweight example, here, of course, it begs to get rid of variantsListand emit an event from variantcatching it in task. But there can be many intermediate components.

Tell me, please, what is the best way to deal with this?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
0
0xD34F, 2021-10-18
@Fedooot01

there can be many intermediate components

provide/inject

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question