Вопрос или проблема
По какой-то причине моё приложение не распознаёт один из атрибутов полученного JSON. Оно получает ‘posts’ и должно формировать ссылки на основе ‘posts.links’. Я пишу этот код:
<Link
v-for="link in props.posts.links"
:key="link.label"
v-if="link.url"
:href="link.url"
class="px-4 py-2 rounded"
:class="{'bg-emerald-400 text-white': link.active, 'bg-gray-200': !link.active}"
>
{{ link.label }}
</Link>
Но я получаю ошибку “TypeError: Невозможно прочитать свойства undefined (чтение ‘url’)”. Если написать жестко (например, posts.links[0].url), то приложение распознаёт атрибут “url”, и всё работает хорошо.
Если заменить v-if="link.url"
на v-if="link !== undefined"
, то появляется другая ошибка: [Vue warn]: Свойство "link" было доступно во время рендеринга, но не определено в экземпляре.
и страница загружается, но навигационная панель страницы не отображается.
При первом рендеринге posts.links
недоступен, попробуйте добавить условное рендеринг, чтобы проверить, доступен ли он:
<template>
<!-- ...-->
<template v-if="posts.links">
<Link
v-for="link in posts.links"
:key="link.label"
:href="link.url"
class="px-4 py-2 rounded"
:class="{'bg-emerald-400 text-white': link.active, 'bg-gray-200': !link.active}"
>
{{ link.label }}
</Link>
</template>
<!-- ...-->
</template>
Обратите внимание, что не следует устанавливать v-if и v-for на одном элементе, также нет необходимости ссылаться на props в шаблоне.
Ответ или решение
Ошибка TypeError: Cannot read properties of undefined (reading 'url')
возникает, когда вы пытаетесь обратиться к свойству объекта, который еще не существует или не инициализирован. В вашем случае вы получаете это сообщение, когда ваш компонент пытается рендерить ссылки из posts.links
, но на первом рендере данные posts.links
еще недоступны.
Для решения этой проблемы важно добавить условную проверку, что данные действительно загружены перед попыткой доступа к их свойствам. Вот как можно переписать ваш код:
<template>
<!-- Проверяем, есть ли данные и существуют ли ссылки -->
<template v-if="props.posts && props.posts.links">
<Link
v-for="link in props.posts.links"
:key="link.label"
v-if="link.url" <!-- Проверяем наличие url перед рендерингом ссылки -->
:href="link.url"
class="px-4 py-2 rounded"
:class="{'bg-emerald-400 text-white': link.active, 'bg-gray-200': !link.active}"
>
{{ link.label }}
</Link>
</template>
</template>
Объяснение изменений:
-
Условная проверка:
- Мы добавили проверку
v-if="props.posts && props.posts.links"
для обеспечения того, чтоposts
иposts.links
существуют перед рендерингом списка ссылок. Это предотвратит попытки доступа к свойствам недоступного объекта.
- Мы добавили проверку
-
Отдельный шаблон для ссылок:
- Убедитесь, что
v-if
иv-for
не находятся на одном элементе. Соответственно,v-if
помещен на обертку<template>
, чтобы избежать потенциальных конфликтов и путаницы.
- Убедитесь, что
-
Свойство
props
:- Для доступа к свойствам компонента нет необходимости указывать
props
. Достаточно использоватьposts
, если они переданы как свойства в компонент.
- Для доступа к свойствам компонента нет необходимости указывать
Используя этот подход, вы избежите ошибок, связанных с попытками обращения к свойствам, которые еще недоступны, что, в свою очередь, улучшит стабильность вашего приложения.