#javascript #angular #angular-lifecycle-hooks
#javascript #угловой #angular-lifecycle-hooks
Вопрос:
Итак, в моем текущем проекте я пытаюсь создать слайдер продуктов.Для правильной работы мне нужно получить ширину всех продуктов, чтобы я мог рассчитать общую ширину.В настоящее время то, что я делаю, это
ngAfterViewInit(): void {
this.service.getData().subscribe((items) => {
for (let key in items) {
this.items.push(items[key]);
}
this.cd.detectChanges();
this.cards = this.elem.nativeElement.querySelectorAll('.card');
console.log(this.cards); // In this log i am getting all the cards have the correct width
this.cards.forEach((card) => {
console.log(card.getBoundingClientRect());//But in this log widths are different
this.totalWidth = card.clientWidth;
});
console.log(this.totalWidth);
});
}
В ngAfterViewInit после вызова моего бэкэнда и установки для него переменной laocal я вручную запускаю обнаружение изменений.После этого, если я регистрирую консоль, я получаю список узлов, в котором все элементы имеют правильную ширину.Но если я попытаюсь перебрать список узлов для получения totalwidth, я получаю разные значения.Здесь на каждой карточке я в настоящее время показываю одно изображение и один текст.Я не устанавливаю ширину карты на фиксированное значение, я устанавливаю высоту изображения на фиксированное значение, применяя ширину, соответствующую этой высоте, чтобы изображение было отзывчивым.Итак, мой цикл по списку узлов дает мне неправильное значение ширины, пока изображение не будет загружено из кэша памяти.Итак, я предполагаю, что для загрузки изображения требуется определенное время, а ширина моей карты зависит от ширины изображений, поэтому я получаю неправильные значения ширины, если пытаюсь перебрать список узлов.Но почему значения ширины верны в списке узлов и почему они меняются, если я пытаюсь перебрать их?Как мне решить эту проблему, чтобы получить общую ширину на основе ширины каждой карты, как только мой компонент загружается без использования setTimeOut()
.
Вот демонстрационный код stackblitz — https://stackblitz.com/edit/angular-ivy-czs5mo?file=src/app/app.component.ts
Комментарии:
1. Почему вы вызываете console.log(card.getBoundingClientRect()), но измеряете общую ширину с помощью clientWidth? Обычно это разные значения
2. Даже если я измеряю с помощью offsetwidth, значение будет другим .. но когда изображения загружаются в кэш памяти или когда-нибудь позже в любой функции, которую я вызываю, одни и те же шаги, оба значения одинаковы .. я пытаюсь получить общую ширину, измеряя ширину каждой карты.
3. Итак, вы говорите, что вам нужно знать, как дождаться загрузки изображений для проверки?
4. прежде всего, я хочу знать, происходит ли такое поведение из-за того, что для загрузки изображения требуется время, для чего ширина каждой карты в списке узлов имеет разную ширину (console.log(this.cards)), а следующая строка, если я попытаюсь перебрать список узлов и получить доступ к ширине каждой карты, имеет совершенно другое значение. И как я могу добиться того, что, как только компонент загружен и изображения отображаются, я могу измерить общую ширину. Я не хочу использовать setTimeout(), потому что мы никогда не узнаем, сколько времени это займет, пока не получим правильные значения ширины.
Ответ №1:
Вам нужно проверить, в ваших изображениях событие (load)
. Некоторым нравится
<img src="https://picsum.photos/200/300" (load)="onLoad()"/>
count:number=0;
yet:boolean=false;
onLoad()
{
count ;
this.checkWidth()
}
ngAfterViewInit()
{
this.yet=true;
this.checkWidth()
}
this.checkWidth()
{
if (this.yet amp;amp; count==imagesLength)
{
..do something..
}
}
ПРИМЕЧАНИЕ: вместо этого используйте
//I don't like so much
this.elem.nativeElement.querySelectorAll('.card');
Вы можете использовать referenceVariable #card
в .html и управлять элементами с помощью ViewChildren
@ViewChildren('card') cards:QueryList<ElementRef>
И использовать
this.cards.forEach(x=>{
const rect=x.nativeElement.getBoundingClientRect()
console.log(rect)
...
})