У меня есть изменение переменной, которое нужно отслеживать, и я хочу запустить какую-то функцию после такого изменения. Итак, я использую хук ngAfterViewChecked для запуска функции. Однако этот метод представляет собой представление данных. Итак, его нужно запустить только один раз. Итак, я использовал логическую переменную состояния, чтобы обработать это следующим образом.
ngAfterViewChecked()
{
//status is a boolean variable which is true
if (this.status)
{
this.status=!this.status;
this.myFunction();
}
}
myFunction
{
//some code
}
Но я обнаруживаю несколько отправок данных в этом подходе (проверено после проверки базы данных), и я также получаю следующую ошибку.
ОШИБКА Ошибка: ExpressionChangedAfterItHasBeenCheckedError: выражение изменилось после проверки. Предыдущее значение для '@dialogContainer': 'enter'. Текущее значение: «выход».
Насколько я знаю, ngAfterViewChecked запускается для каждого изменения. Поэтому я предполагаю, что до изменения статуса на false выполнялся другой экземпляр if (this.status){} до того, как он был изменен на false.
Есть ли способ решить эту проблему?
@ Андрей Вы предлагаете мне послушать изменение значения this.status? Я не получил ваш комментарий
Я еще ничего не предлагал. чтобы предоставить вам лучший вариант, мне нужно знать сценарий, как меняется this.status
@Andrei Андрей, я делал это внутри предложения if, чтобы убедиться, что оно больше не запустится. если (this.status) { this.status=!this.status; эта.моя функция(); }
@ Андрей Что-то не так с моим предложенным ответом?
Я бы сказал, что ваш ответ решает небольшую архитектурную ошибку, которая появилась раньше. Лучший способ - вызвать вашу логику, когда событие (которое в вашем случае обновляет "this.status") испускается. отслеживание переменных так, как вы пытаетесь, считается плохой практикой. Это одна из причин, по которой AngularJS мертв, а вместо него создается Angular2+.
@Andrei Так что я должен вызвать myFunction(), когда this.status выдается следующим образом. ngAfterViewChecked() { if (this.counter == 0) { this.counter++; если (this.counter == 1) { this.paymentListener.next(this.counter); эта.моя функция(); } } } Это правильно?
как я уже сказал, правильный способ - не использовать ngAfterViewChecked
крючок. его называют слишком часто. Недостаточно контекста, чтобы помочь вам с точным вариантом, который вам нужен
После нескольких часов поиска я смог это преодолеть. Вот как я это сделал. Я начну с небольшого объяснения моего решения.
Сначала я создал тему с именем paymentListener, целочисленную переменную с именем counter и подписку с именем oneTimePayment.
oneTimePayment: Subscription;
private paymentListener = new Subject<number>();
counter = 0;
Затем внутри метода onInit я сделал подписку.
ngOnInit() {
this.oneTimePayment = this.paymentListener.subscribe((counter) => {
if (counter == 1) {
//this is my function
this.myFunction();
}
});
}
Затем внутри хука жизненного цикла ngAfterViewChecked я использовал paymentListener (это Subject) для выдачи значения счетчика.
ngAfterViewChecked() {
if (this.counter == 0) {
this.counter++;
if (this.counter == 1) {
this.paymentListener.next(this.counter);
}
}
}
Поскольку значение выдается обработчиком платежа (Subject) только в том случае, если счетчик равен 1. Таким образом, при подписке, сделанной внутри onInt, будет получено выданное значение, и там я выполняю myFunction() только в том случае, если выданное значение равно 1; Это гарантирует, что метод запускается только один раз после изменения.
Наконец, обязательно вызовите отмену подписки внутри ngOnDestroy. В противном случае это приведет к утечке памяти.
ngOnDestroy() {
this.oneTimePayment.unsubscribe();
}
ngAfterViewChecked — плохой хук для решения проблемы в 999 случаях из 1000. Что за сценарий
this.status
обновлен?