首页 > 解决方案 > 在这种情况下,组织 Vue.js 组件之间通信的最佳方式是什么?

问题描述

我有一个数组

[
  {
    "id": 0,
    "title": "Task #1",
    "description": "Task description",
    "solutions": [
      {
        "solutionId": 0,
        "text": "First solution text",
        "isMarked": true
      },
      {
        "solutionId": 1,
        "text": "Second solution text",
        "isMarked": false
      }
    ]
  },
  {
    "id": 1,
    "title": "Task #2",
    "description": "Task description",
    "solutions": [
      {
        "solutionId": 0,
        "text": "First solution text",
        "isMarked": true
      },
      {
        "solutionId": 1,
        "text": "Second solution text",
        "isMarked": true
      },
      {
        "solutionId": 2,
        "text": "Third solution text",
        "isMarked": true
      }
    ]
  }
]

它表示任务和解决方案变体的列表。

我需要一个机会来切换isMarked解决方案的价值,true/false只需点击它。

我创建了一个这样的组件结构:

// index.vue
<template>
   <div class="task-list">
      <Task v-for="task in tasks" :key="task.id" :task="task" />
   </div>
</template>

<script>
// ...
data() {
   return {
      tasks: [/* the array of tasks */]
   }
}
</script>
// task.vue
<template>
   <div>
      <h1>{{ task.title }}</h1>
      <p>{{ task.description }}</p>
      <SolutionsList :solutions="task.solutions" />
   </div>
</template>

// ...
// solutionsList.vue
<template>
   <div>
      <Solution v-for="solution in solutions" :key="solution.id" :solution="solution" />
   </div>
</template>

// ...
// solution.vue
<template>
<div>
      <p>{{ solution.text }}</p>
      <span @click="toggleMark">{{ markLabel }}</span>
   </div>
</template>

<script>
// ...
computed: {
   markLabel() {
      return solution.isMarked ? 'Unmark' : 'Mark'
   }
},
methods: {
   toggleMark() {
      // ???
   }
}
</script>

例如,我可以将此状态存储在 Vuex 中,而data()不是index.vue. 而且我需要进行 API 调用以更改 isMarked单击的任务解决方案的值。

问题来了:最好的方法是什么?如果solutionId是唯一的最后手段,我可​​以遍历 Vuex 中的所有任务以找到它solutionId并在那里更改状态。但在这种情况下solutionId,并不是所有任务都是唯一的。

我看到了哪些解决方案:

  1. 使用单独的道具将任务传递id给每个人。但是在这种情况下,如果组件是深度嵌套的并且它可以是深度嵌套Solution的,我需要为每个组件创建很多道具。Solution

  2. 最好只toggleMark从组件发出事件Solution并在组件中捕获它,Task但在我的深度嵌套Solution组件的情况下,我需要在每个父组件中重新发出它以Task.

  3. 我可以在Solution组件中调用 Vuex 操作来 mutate isMarked。但是我仍然需要一个任务id来找到一个包含这个点击解决方案的父任务。

  4. 我可以使用事件总线,但它在现代方法中并不受欢迎。

  5. 例如,我可以创建另一个计算方法并将每个方法与它们的父任务index.vue映射以创建一个新字段并传递结果对象而不是. 但它看起来有点脏。solutionidtaskIdtasks

  6. provide / inject至少可以使用。对于这种情况,这将是一个很好的解决方案。但是如果Solution不是 a 的子组件,Task它会在随机位置。

这只是一个轻量级的问题示例。当然,只要扔掉SolutionsList并发出toggleMark事件就完美了,但是组件的中间组件Solution可能很多,或者它可能不是组件的子Task组件。

请告诉我如何以最好的方式解决这个问题?

标签: vue.jsvue-component

解决方案


推荐阅读