#vue.js
#vue.js
Вопрос:
Пытаюсь получить « displayImages
массив как вычисляемое свойство. Использование значения по умолчанию « selected
property = 0
. this.selected изменяется соответствующим образом при наведении курсора мыши и событиях щелчка.
При попытке получить вычисленное « displayImages
он говорит:
"this.variations[this.selected] is undefined."
Я использую api для получения данных и изображений моего продукта.
<template>
<div id="product-page">
<v-card width="100%" class="product-card">
<div class="image-carousel">
<v-carousel height="100%" continuos hide-delimiters>
<v-carousel-item
v-for="(image, i) in displayImages"
:key="i"
:src="image"
>
</v-carousel-item>
</v-carousel>
</div>
<div class="details">
<h2>{{ this.title }}<br />Price: ${{ this.price }}</h2>
<p>{{ this.details }}</p>
<ul style="list-style: none; padding: 0">
<li
style="border: 1px solid red; width: auto"
v-for="(color, index) in variations"
:key="index"
@mouseover="updateProduct(index)"
@click="updateProduct(index)"
>
{{ color.color }}
</li>
</ul>
<div class="buttons">
<v-btn outlined rounded
>ADD TO CART<v-icon right>mdi-cart-plus</v-icon></v-btn
>
<router-link to="/shop">
<v-btn text outlined rounded> BACK TO SHOP</v-btn>
</router-link>
</div>
</div>
</v-card>
</div>
</template>
<script>
export default {
name: "Product",
props: ["APIurl"],
data: () => ({
title: "",
details: "",
price: "",
variations: [],
selected: 0,
}),
created() {
fetch(this.APIurl "/products/" this.$route.params.id)
.then((response) => response.json())
.then((data) => {
//console.log(data);
this.title = data.title;
this.details = data.details.toLowerCase();
this.price = data.price;
data.variations.forEach((element) => {
let imagesArray = element.photos.map(
(image) => this.APIurl image.url
);
this.variations.push({
color: element.title,
images: imagesArray,
qty: element.qty,
productId: element.productId,
});
});
});
},
computed: {
displayImages() {
return this.variations[this.selected].images;
},
},
methods: {
updateProduct: function (index) {
this.selected = index;
console.log(index);
}
},
};
</script>
Комментарии:
1. Это потому, что при первом отображении вашего DOM
this.variations
массив пуст и поэтомуthis.variations[this.selected]
возвращает значение undefined . Попытки доступа.images
кundefined
объекту выдадут ошибку. Вы должны добавить защитное предложение, где, если оно не определено, просто верните пустой массив.2. @Terry спасибо!… любой другой способ предотвратить это, возможно, с помощью надлежащих перехватов жизненного цикла? или это способ сделать это .. еще раз спасибо
3. Насколько я знаю, нет, поскольку массив заполняется асинхронно, поэтому он всегда пуст в начале.
4. @Terry спасибо .. если вы хотите, чтобы я принял ваш ответ, вам нужно «ответить на вопрос» ниже
5. Считайте, что это сделано 🙂
Ответ №1:
Чтобы должным образом расширить мой комментарий, причина, по которой вы сталкиваетесь с ошибкой, заключается в том, что при обращении к вычисляемому в шаблоне this.variations
это пустой массив. Оно заполняется только асинхронно, поэтому, скорее всего, оно пустое, когда VueJS пытается использовать его при рендеринге виртуального DOM.
По этой причине будет возвращен доступ к элементу внутри него по индексу (заданному как this.selected
) undefined
. Поэтому попытка получить доступ к свойству, вызываемому images
в undefined
объекте, вернет ошибку.
Чтобы устранить эту проблему, все, что вам нужно, это ввести защитное предложение в ваш вычисляемый как таковой:
computed: {
displayImages() {
const variation = this.variations[this.selected];
// GUARD: If variation is falsy, return empty array
if (!variation) {
return [];
}
return variation.images;
},
}
Бонусный совет: если вы однажды захотите использовать TypeScript, вы можете даже упростить его как таковой… но это обсуждение для другого дня 😉 на данный момент необязательная цепочка и оператор объединения с нулевым значением поддерживаются только новейшими версиями браузеров evergreen.
computed: {
displayImages() {
return this.variations[this.selected]?.images ?? [];
},
}
Ответ №2:
Чтобы избежать такого рода ошибок, вы должны использовать свойство безопасной навигации.
Помните, что это полезно только при загрузке приложения.
Попробуйте что-то подобное:
<script>
export default {
name: 'Product',
computed: {
displayImages() {
if (this.variations[this.selected]) {
return this.variations[this.selected].images;
}
return [];
},
},
};
</script>