#angular #error-handling
#angular #обработка ошибок
Вопрос:
Я пытаюсь создать адаптивный стиль компонента. Разберитесь с изменением размера Windows. Значение будет выдаваться выражением GetRight().
Мой HTML:
<div [hidden]="index > 3" [style.right]="getRight()" class="chat-box card">
............
</dv>
В моем компоненте.ts
import { Component, HostListener } from '@angular/core';
@Component({
selector: 'app-chat-box',
templateUrl: './chat-box.component.html',
styleUrls: ['./chat-box.component.scss']})
export class ChatBoxComponent implements OnInit {
@HostListener('window:resize', ['$event'])
onResize(event) {this.currentWidth = event.target.innerWidth;}
currentWidth: number;
constructor(){}
ngOnInit() {}
getRight() {
if(this.currentWidth <= 700 || window.innerWidth <= 700){
if(this.currentWidth){
return ((this.currentWidth -320)/2).toString() 'px';
}
return ((window.innerWidth -320)/2).toString() 'px';
}
if(this.index==1 amp;amp; window.innerWidth > 700 ){
return '380px';
}
return (380 330).toString() 'px';} }
И сообщение об ошибке будет:
ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'right: 710px'. Current value: 'right: 11px'.
Ответ №1:
Это не так, как вы должны это делать. Эта функция будет вызываться с каждым циклом обнаружения изменений. Лучше отреагировать на изменение размера и только потом вычислять его. Намного более производительный:
<div [hidden]="index > 3" [style.right.px]="right" class="chat-box card"></div>
export class ChatBoxComponent implements OnInit {
right: number;
@Input()
index?: number;
@HostListener('window:resize')
setRight() {
const width = window.innerWidth;
if (width <= 700) {
this.right = ((width - 320) / 2);
} else if (this.index === 1 amp;amp; width > 700) {
this.right = 380;
} else {
this.right = 380 330;
}
}
ngOnInit(): void {
this.setRight();
}
ngOnChanges(changes: SimpleChanges): void {
if (changes.index) {
this.setRight();
}
}
}
Я игнорирую некоторую странную логику, которую вы реализовали, но я предлагаю вам также лучше взглянуть на руководства angular по angular.io
Однако я могу предложить вам использовать OnPush
стратегию обнаружения изменений. Это уже значительно уменьшит количество ExpressionHasChanged
ошибок, сделает ваше приложение более производительным и повысит логику обнаружения изменений.
Более продвинутым способом было бы использовать async
канал в сочетании с rxjs
:
<div [hidden]="(index$ | async) > 3" [style.right.px]="right$ | async" class="chat-box card"></div>
export class ChatBoxComponent {
@Input()
set index(index: number) {
this.index$.next(index || 0);
}
readonly index$ = new BehaviorSubject<number>(0);
readonly right$: Observable<number> = combineLatest([
this.index$,
fromEvent(window, 'resize').pipe(
startWith<Event, void>(void 0)
)
]).pipe(
map(([index]) => this.getRight(index))
);
private getRight(index: number): number {
const width = window.innerWidth;
if (width <= 700) {
return (width - 320) / 2;
}
if (index === 1 amp;amp; width > 700) {
return 380;
}
return 380 330;
}
}
Комментарии:
1. Спасибо, но это изменение не влияет на правильное значение при изменении размера окна.
2. @ChanchenPork Я обновил свой ответ с помощью stackblitz, в котором реализованы оба вышеуказанных решения, и если вы измените размер iframe справа, вы увидите, что правая часть обновляется, когда эта панель меньше 700
3. Вау, это работа для меня, спасибо. Но если я хочу увеличить this.index на количество открытых окон чата. например, я открываю два компонента чата. Итак, индекс = 2.
4. @ChanchenPork Я ввел индекс
@Input()
?5. Нет, индекс объявлен в классе.