Я новый студент факультета компьютерных наук, и у меня есть школьный проект на Vue.js. Он работает, но показывает следующее предупреждение:
[Предупреждение Vue]: у вас может быть бесконечный цикл обновления в функции рендеринга компонента.
Английский не мой родной язык, так что извините, если я заранее напишу что-то не так, но я постараюсь объяснить, что я должен делать на проекте.
Мне нужно создать фотосетку/альбом, в каждой строке которого отображается не более 3 фотографий. Что-то вроде этого: Пример того, как это должно выглядеть
Код такой:
<template>
<v-container>
<!-- 'v-container' est´substituindo ' div class = "clubes-lista" '-->
<div class = "grid-photo">
<v-container class = "grey lighten-3">
<v-row
v-for = "index in numberLines()"
:key = "index"
class = "grey lighten-3"
>
<v-col v-for = "n in 3" :key = "n" cols = "4">
<v-card v-if = "numberPhotos > checkInsertedAllPhotos()" outlined>
<v-img
src = "https://i.pinimg.com/736x/96/28/b7/9628b7892fd0543782f53eeec4bae502.jpg"
alt = "Bird Photo"
>
</v-img>
<div class = "photo-subtitle">
<v-icon size = "15">mdi-heart-outline</v-icon>
<p>The Cockatiel</p>
</div>
</v-card>
<v-card v-else></v-card>
</v-col>
</v-row>
</v-container>
</div>
</v-container>
<script>
export default {
name: "PhotoGrid",
data() {
return {
listPhotosOnGrid: [],
numberPhotos: 0,
numberTotalLines: 0,
countPhotos: 0,
};
},
computed: {},
methods: {
createPhotosList() {
var listPhotos = [];
for (var i = 0; i < 10; i++) {
var aux = {
id: i + 1,
src:
"https://i.pinimg.com/736x/96/28/b7/9628b7892fd0543782f53eeec4bae502.jpg",
subtitle: "The cockatiel",
};
listPhotos.push(aux);
}
this.listPhotosOnGrid = listPhotos;
this.numberPhotos = listPhotos.length;
},
numberLines() {
this.createPhotosList();
var photosMultipleThree = this.numberPhotos;
while (photosMultipleThree % 3 != 0) {
photosMultipleThree = photosMultipleThree + 1;
}
this.numberTotalLines = photosMultipleThree / 3;
return photosMultipleThree / 3;
},
checkInsertedAllPhotos() {
var cont = this.countPhotos++;
return cont;
},
},
};
<style scoped>
.photo-subtitle {
font-size: 10px;
display: flex;
flex-direction: row;
justify-content: left;
align-items: flex-start;
padding: 0;
margin-top: 10px;
}
.photo-subtitle p {
margin-left: 5px;
}
Итак... Пытаясь понять, что происходит, я думаю, что предупреждение исходит из следующей строки:
<v-card v-if = "numberPhotos > checkInsertedAllPhotos()" outlined>
Если, потому что он не может показать больше изображений, чем дано. Например, в каждой строке отображается 3 фотографии, поэтому, если у меня нет общего количества фотографий, кратного os 3, я не хочу заполнять все столбцы в последней строке, а только те, которые необходимы для отображения всех фотографий.
Но я просто думаю, основываясь на некоторых тестах, я не уверен, исходит ли предупреждение из этой строки.
Код работает, но я чувствую, что что-то не так. (На самом деле это работает частично, потому что я до сих пор не знаю, как получить информацию из массива для отображения, поэтому он повторяет одно и то же)
Я хочу научиться делать это правильно.
Кто-нибудь может сказать мне, что я могу сделать, чтобы предупреждение исчезло, или мне нужно все изменить и создать новую логику, чтобы она работала правильно.
Я просто хочу учиться.
Большое вам спасибо и еще раз извините, если это глупый вопрос, или если я все делаю неправильно, хе-хе. И извините, если что не так написал.
:)
3. Не рекомендуется использовать v-if внутри v-for. Вместо этого, используя вычисляемые свойства, сначала фильтруйте массив, а затем перебирайте отфильтрованный массив.
Я посмотрел на ваш код. Во-первых, я бы порекомендовал вам перестать использовать ключевое слово var
, а вместо этого использовать let
или const
(вы можете проверить вопрос здесь и взглянуть на область действия, основанную на этом ключевом слове, область действия var
очень необычна в настоящее время, и это приведет к вы к некоторым вопросам).
Что касается вашей конкретной проблемы с бесконечным циклом обновления, проблема связана с вашей функцией checkInsertedAllPhotos
. Я бы объяснил это так:
В v-if внутренние механизмы Vue проверяют, должен ли элемент отображаться, вызывая функцию checkInsertedAllPhotos
При выполнении функции checkInsertedAllPhotos
данные countPhotos
увеличиваются (кстати лучше было бы просто сделать
this.countPhotos ++; return this.countPhotos;
Поскольку данные были изменены, Vue запускает повторный рендеринг страницы.
Поскольку происходит повторный рендеринг, Vue проверяет в v-if, должен ли элемент рендериться, вызывая функцию checkInsertedAllPhotos
.
И это может быть бесконечно, если Vue не предотвратит это!
Я бы предложил немного переработать вашу логику. Однако быстрым решением вашей проблемы было бы то, что когда вы проверяете индекс в своем списке: например, если вы хотите отобразить listPhotosOnGrid[i]
, вы проверяете, если i<numberPhotos
с помощью v-if, а в v-else вы можете отобразить что-то еще если ты хочешь.
Я также думаю, что вы могли бы иметь гораздо более простой код, используя css (например, css-grid). У вас может быть что-то простое:
<div v-for = "n in 100">
<img v-bind:src = "`https://i.pinimg.com/photos/${n}.png`">
</div>
и некоторые css для его стилизации и имеют только 3 элемента в строке. Если вы хотите узнать о css-grid, я бы порекомендовал документацию Mozzila или следующий учебник.
Прямо сейчас у меня есть небольшая проблема с пониманием точного вопроса, так как внутри есть несколько тем для решения, но я надеюсь, что мое объяснение бесконечного цикла поможет вам!
Получайте удовольствие, изучая Vue!
Спасибо всем, кто помог мне, и вы, безусловно, помогли мне!!!!
Извините, что смог ответить только сегодня. Я думаю, что смог сделать код намного лучше, я многое изменил, особенно логику кода. И я думаю, что это может стать еще лучше, но я точно уже добился большого прогресса, хе-хе.
Я немного не хотел публиковать этот вопрос, потому что, хотя в то время, когда я его публиковал, я не знал, что делать, у меня было ощущение, что это что-то глупое (например, глупый вопрос), и что я только отнял бы время у любого, кто остановился на моем вопросе. Но я получил только удивительные ответы, все были такими терпеливыми, так что СПАСИБО ВАМ БОЛЬШОЕ!!
(Я также новичок в StackOverflow, поэтому надеюсь, что все делаю правильно, хе-хе)
Прежде всего, 1. эта функция
checkInsertedAllPhotos()
всегда возвращает 1, потому что вы увеличиваете 1 только один раз. 2.v-for = "index in numberLines()"
Здесь numberLines() является числом, потому что вы возвращаете photosMultipleThree / 3. Вы не можете перебрать число в цикле.