Из документов:
detectChanges (): void
Проверяет детектор изменений и его дочерние элементы.
Это означает, что в случае, когда какая-либо вещь внутри вашей модели (вашего класса) изменилась, но она не отражала представление, вам может потребоваться уведомить Angular, чтобы обнаружить эти изменения (обнаружить локальные изменения) и обновить представление.
Возможные сценарии могут быть:
1- Детектор изменений отсоединен от вида (см. Отсоединение )
2- Произошло обновление, но оно не было внутри Angular Zone, поэтому Angular не знает об этом.
Например, когда сторонняя функция обновила вашу модель, и вы хотите обновить представление после этого.
someFunctionThatIsRunByAThirdPartyCode(){
yourModel.text = "new text";
}
Поскольку этот код находится за пределами зоны Angular (возможно), вам, скорее всего, необходимо убедиться, что обнаружены изменения и обновлено представление, таким образом:
myFunction(){
someFunctionThatIsRunByAThirdPartyCode();
// Let's detect the changes that above function made to the model which Angular is not aware of.
this.cd.detectChanges();
}
ПРИМЕЧАНИЕ :
Есть и другие способы заставить работать выше, иными словами, есть и другие способы внести это изменение в цикл угловых изменений.
** Вы можете обернуть эту стороннюю функцию внутри zone.run:
myFunction(){
this.zone.run(this.someFunctionThatIsRunByAThirdPartyCode);
}
** Вы можете обернуть функцию внутри setTimeout:
myFunction(){
setTimeout(this.someFunctionThatIsRunByAThirdPartyCode,0);
}
3. Есть также случаи, когда вы обновляете модель после ее change detection cycle
завершения, где в этих случаях вы получаете эту страшную ошибку:
«Выражение изменилось после того, как оно было проверено»;
Обычно это означает (на языке Angular2):
Я увидел изменение в вашей модели, которое было вызвано одним из моих принятых способов (события, запросы XHR, setTimeout и ...), а затем я запустил обнаружение изменений, чтобы обновить ваше представление, и я завершил его, но затем появился другой функция в вашем коде, которая снова обновила модель, и я не хочу снова запускать обнаружение изменений, потому что больше нет грязной проверки, как AngularJS: D и мы должны использовать односторонний поток данных!
Вы обязательно столкнетесь с этой ошибкой: P.
Несколько способов это исправить:
1- Правильный путь : убедитесь, что обновление находится в цикле обнаружения изменений (обновления Angular2 - это односторонний поток, который происходит один раз, не обновляйте модель после этого и не перемещайте код в лучшее место / время).
2- Ленивый способ : после того, как это обновление запустит detectChanges (), чтобы сделать angular2 счастливым, это определенно не лучший способ, но, как вы спросили, каковы возможные сценарии, это один из них.
Таким образом, вы говорите: я искренне знаю, что вы запустили обнаружение изменений, но я хочу, чтобы вы сделали это снова, потому что мне нужно было что-то обновить на лету после того, как вы закончили проверку.
3- Поместите код внутри setTimeout
, потому что setTimeout
пропатчен по зонам и будет работать detectChanges
после его завершения.
Из документов
markForCheck() : void
Отмечает всех предков ChangeDetectionStrategy как проверяемые.
Это главным образом необходимо, когда ChangeDetectionStrategy вашего компонента - OnPush .
OnPush сам по себе означает, что запускать обнаружение изменений можно только в том случае, если произошло что-то из этого:
1- Один из @inputs компонента был полностью заменен новым значением, или, проще говоря, если ссылка на свойство @Input полностью изменилась.
Итак, если ChangeDetectionStrategy вашего компонента - OnPush, и тогда у вас есть:
var obj = {
name:'Milad'
};
И затем вы обновляете / видоизменяете это как:
obj.name = "a new name";
Это не обновит ссылку на obj , следовательно, обнаружение изменений не будет запущено, поэтому представление не отражает обновление / мутацию.
В этом случае вы должны вручную указать Angular для проверки и обновления представления (markForCheck);
Так что, если вы сделали это:
obj.name = "a new name";
Вам нужно сделать это:
this.cd.markForCheck();
Скорее, ниже приведёт к запуску обнаружения изменений:
obj = {
name:"a new name"
};
Который полностью заменил предыдущий объект новым {}
;
2- Событие сработало, как щелчок, или что-то подобное, или любой из дочерних компонентов отправил событие.
События как:
- щелчок
- KeyUp
- События подписки
- и т.п.
Итак, вкратце:
Используйте, detectChanges()
когда вы обновили модель после того, как angular запустил ее обнаружение изменений, или если обновление вообще не было в angular мире.
Используйте, markForCheck()
если вы используете OnPush и обходите его ChangeDetectionStrategy
, изменяя некоторые данные, или вы обновили модель внутри setTimeout ;