Динамические компоненты Vue не рендерятся повторно внутри цикла v-for при изменении данных

#javascript #vue.js

#javascript #vue.js

Вопрос:

У меня есть компонент динамической таблицы, в котором я могу изменять столбцы (упорядочивать, добавлять новые, удалять столбцы). Тело таблицы выглядит следующим образом:

 <tr v-for="row in data" :key="row.id">
        <td v-for="column in columns" :key="column.slug">
          <component
            v-if="column.component"
            :is="column.component"
            v-bind="{ row: row, countries: row.reach }"
          />
          <template v-else>
            {{ row[column.slug] }}
          </template>
        </td>
      </tr>
  

Все работает хорошо, за исключением случаев, когда я редактирую data (добавляю новый столбец или меняю порядок), тогда каждый компонент внутри тела таблицы исчезает и не отображается. Я пытался прикрепить unique :key к <component> , но не смог заставить его работать. Когда я проверяю тело таблицы в Vue devtools, я вижу, что компоненты внутри просто не отображаются в DOM. При проверке тела таблицы в chrome devtools я вижу только <!--function(e,n,r,o){return dn(t,e,n,r,o,!0)}--> в том месте, где должен отображаться компонент. Есть идеи, что я могу здесь делать неправильно?

Комментарии:

1. Вы проверяли data значение после редактирования?

2. @Dmitry да, внутри все в порядке, но теперь я получаю некоторые ошибки для каждого компонента: Failed to mount component: template or render function not defined. и Error in beforeCreate hook: "TypeError: Cannot read property 'call' of null"

3. О, я не заметил template элемента внутри. Какова цель этого элемента? Вероятно, вам следует изменить его на простой div .

4. Это был просто заполнитель для v-if директивы. Я изменил его на div , но все равно получаю тот же результат

5. Хорошо, тогда, возможно, вы не зарегистрировали некоторые компоненты, с помощью которых пытаетесь выполнить рендеринг :is="column.component" . Или, может быть, некоторые из ваших column.component значений являются null / undefined после редактирования? Попробуйте обернуть component элемент внутри другого div с v-if="column.component" помощью.

Ответ №1:

Вы используете дублированные ключи. Вы должны предоставить уникальные ключи для всех v-for элементов внутри всего компонента. Попробуйте это (см. key для каждого столбца):

       <tr v-for="row in data" :key="row.id">
        <td v-for="column in columns" :key="`${row.id}/${column.slug}`">
          <component
            v-if="column.component"
            :is="column.component"
            v-bind="{ row: row, countries: row.reach }"
          />
          <template v-else>
            {{ row[column.slug] }}
          </template>
        </td>
      </tr>
  

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

Комментарии:

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

Ответ №2:

Оказывается, я передавал объект компонента в :is директиву вместо string имени компонента. Вот почему это не было отображено должным образом.

Комментарии:

1. Привет, не могли бы вы привести мне рабочий пример? У меня такая же проблема. Спасибо

2. например, если вы импортируете свой компонент в файл vue следующим образом: import ExampleComponent from "./ExampleComponent"; затем в вашей :is директиве вам нужно передать его следующим образом: :is="'ExampleComponent'" not this: :is="ExampleComponent" . Другими словами, вам нужно передать имя компонента, а не сам компонент