Ошибка при запросе: ключ должен быть помещен в <шаблон>

За отсутствие :key="item.id" на <template>, Я получаю эту ошибку:

Но когда я все же помещаю его туда как таковой:

<template v-for="item in Object.values(cart)" :key="item.id">

… Тогда я получаю эту ошибку:

Вот рассматриваемый код:

          <template v-for="item in Object.values(cart)">
            <tr :key="item.id">
              <td>Digest {{ item.digestId }}</td>
              <td>{{ item.duration_text }} subscription</td>
              <td class="price-cell">${{ roundMoney(item.price, 2) }}</td>
              <td class="trash-cell">
                <fa-icon icon="times-circle" size="lg" @click="removeItem(item)" />
              </td>
            </tr>
            <tr v-if="item.discounts.length" :key="`${item.id}-${item.discounts && item.discounts[0].id}`">
              <td colspan="2">
                <label>Code: {{ item.discounts[0].code }}</label>
              </td>
              <td colspan="2">
                <span class="discount-amount">–${{ item.discounts[0].percent_off }}</span>
              </td>
              <td class="trash-discount-cell">
                <fa-icon icon="times-circle" class="trash" @click="rmDscnt(item.discounts[0])" />
              </td>
            </tr>
          </template>

Как я могу обойти эту кажущуюся круговой проблему?

5 ответов

Хотя с этого вопроса прошел год, недавно я столкнулся с подобной проблемой в обсуждениях с другими и нашел причину проблемы. Я надеюсь, что мой ответ поможет другим друзьям, которые увидят этот ответ.

Тег спрашивающего — vue3. В vue3 стандартный синтаксис v-for используется в теге шаблона для записи ключа в теге шаблона. См. официальный документ здесь: https://v3.vuejs.org/guide/list.html#v-for-on-a-template.

следующим образом:

      <template v-for="item in Object.values(cart)" :key="item.id">

Я думаю, что причина ошибки бесконечного цикла вопрошающего заключается в том, что правила vue2 и vue3 используются одновременно. Мой проект vue2 также использует плагин volar, чтобы вызвать эту ошибку. Используйте v-for в теге шаблона, vue2 и vue3 используют два типа правил.

vue2: vue/no-v-for-template-keyvue3: vue/no-v-for-template-key-on-child

Эти два правила противоречат друг другу. Вот официальный руководящий документ: https://eslint.vuejs.org/rules/no-v-for-template-key-on-child.html .

Я не дал решения, потому что мне непонятна другая конфигурация вопрошающего, но я думаю, что нашел причину, и надеюсь помочь вам решить проблему.

Недавно я получил эту ошибку и смог ее исправить, настроив Volar на использование Vue 2.7.

      // tsconfig.json
{
  "compilerOptions": {
    // ...
  },
  "vueCompilerOptions": {
    "target": 2.7,
    // "target": 2, // For Vue version <= 2.6.14
  }
}

Как объяснили другие, Vue.js будет использовать тег для рендеринга и компиляции, на самом деле он не будет существовать в DOM. Ключи необходимы, чтобы алгоритм различения Vue мог различать разные экземпляры компонентов.

Тем не менее, после проверки вашего примера я понял, что вам здесь не нужно, я предполагаю, что вы находитесь внутри тега или, поэтому вы можете просто v-для самого себя.

Пример:

    <table>
    <tbody>
        <tr v-for="item in Object.values(cart)" :key="item.id">
            <td>Digest {{ item.digestId }}</td>
            <td>{{ item.duration_text }} subscription</td>
            <td class="price-cell">${{ roundMoney(item.price, 2) }}</td>
            <td class="trash-cell">
                <fa-icon icon="times-circle" size="lg" @click="removeItem(item)" />
            </td>
        </tr>
        <tr v-if="item.discounts.length" :key="`${item.id}-${item.discounts && item.discounts[0].id}`">
            <td colspan="2">
                <label>Code: {{ item.discounts[0].code }}</label>
            </td>
            <td colspan="2">
                <span class="discount-amount">–${{ item.discounts[0].percent_off }}</span>
            </td>
            <td class="trash-discount-cell">
                <fa-icon icon="times-circle" class="trash" @click="rmDscnt(item.discounts[0])" />
            </td>
        </tr>
    </tbody>
</table>

Я воспользуюсь возможностью дать вам еще один совет, который я использую в своих собственных кодах, вместо использования атрибутов записи, например, 'item.id', я использую индекс, сгенерированный циклом, который всегда будет иметь последовательность, избегающую повторяющихся ошибок и самое главное, он всегда будет иметь действительное значение.

Пример:

<tr v-for="(item, index) in Object.values(cart)" :key="`items_${index}`">

Если это вам поможет, отметьте ответ.

Удачного кодирования!

В Vue.js <template> не может быть задействован, потому что он используется vue для рендеринга и компиляции компонентов.

Попробуйте использовать другие элементы, такие как div, разделы и другие.

Vue использует тег шаблона, чтобы узнать, является ли компонент компонентом, как и реагировать, вы должны вернуть один элемент, попробуйте это:

      <template>
        <div>
         <section v-for="item in Object.values(cart)">
        <tr :key="item.id">
          <td>Digest {{ item.digestId }}</td>
          <td>{{ item.duration_text }} subscription</td>
          <td class="price-cell">${{ roundMoney(item.price, 2) }}</td>
          <td class="trash-cell">
            <fa-icon icon="times-circle" size="lg" @click="removeItem(item)" />
          </td>
        </tr>
        <tr v-if="item.discounts.length" :key="`${item.id}-${item.discounts && item.discounts[0].id}`">
          <td colspan="2">
            <label>Code: {{ item.discounts[0].code }}</label>
          </td>
          <td colspan="2">
            <span class="discount-amount">–${{ item.discounts[0].percent_off }}</span>
          </td>
          <td class="trash-discount-cell">
            <fa-icon icon="times-circle" class="trash" @click="rmDscnt(item.discounts[0])" />
          </td>
        </tr>
        </section>
        </div>
      </template>
Другие вопросы по тегам