В чем разница между markForCheck () и detectChanges ()

В чем разница между ChangeDetectorRef.markForCheck() и ChangeDetectorRef.detectChanges() ?

Я только нашел информацию о SO относительно разницы между NgZone.run() , но не между этими двумя функциями.

Для получения ответов только с ссылкой на документ, пожалуйста, проиллюстрируйте некоторые практические сценарии, чтобы выбрать один из них.

    2 Solutions collect form web for “В чем разница между markForCheck () и detectChanges ()”

    Из документов:

    detectChanges (): void

    Проверяет детектор изменений и его детей.

    Это означает, что, если есть случай, когда какая-либо вещь внутри вашей модели (вашего classа) изменилась, но она не отразила представление, вам может потребоваться уведомить Angular, чтобы обнаружить эти изменения (обнаружить локальные изменения) и обновить представление.

    Возможными сценариями могут быть:

    1- Извещатель изменения отсоединяется от вида (см. Отсоединение )

    2- Произошло обновление, но оно не было внутри Угловой зоны, поэтому 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, и мы должны использовать односторонний stream данных!

    Вы обязательно столкнетесь с этой ошибкой: P.

    Пара способов исправить:

    1- Правильный способ : убедитесь, что обновление находится внутри цикла обнаружения изменений (обновления Angular2 – это односторонний stream, который происходит один раз, после этого не обновляйте модель и переместите код в лучшее место / время).

    2- Lazy way: запустите 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" }; 

    Что полностью заменило предыдущий obj новым {} ;

    2- Событие выстрелило, как щелчок или что-то в этом роде, или какой-либо из дочерних компонентов выбрал событие.

    События, подобные:

    • Нажмите
    • KeyUp
    • События подписки
    • и т.п.

    Короче говоря:

    • Используйте detectChanges() когда вы обновили модель после того, как угловой detectChanges() ее обнаружение изменений или если обновление не было в угловом мире вообще.

    • Используйте markForCheck() если вы используете OnPush, и вы markForCheck() ChangeDetectionStrategy , изменяя некоторые данные или обновляя модель внутри setTimeout ;

    Самое большое различие между ними состоит в том, что detectChanges() фактически вызывает обнаружение изменений, в то время как markForCheck() не вызывает обнаружение изменений.

    detectChanges

    Этот используется для запуска обнаружения изменений для дерева компонентов, начиная с компонента, который вы запускаете detectChanges() . Таким образом, обнаружение изменений будет выполняться для текущего компонента и всех его дочерних элементов. Угловое содержит ссылки на дерево корневых компонентов в ApplicationRef и когда происходит любая операция async, он вызывает обнаружение изменений этого корневого компонента с помощью метода tick() :

     @Injectable() export class ApplicationRef_ extends ApplicationRef { ... tick(): void { if (this._runningTick) { throw new Error('ApplicationRef.tick is called recursively'); } const scope = ApplicationRef_._tickScope(); try { this._runningTick = true; this._views.forEach((view) => view.detectChanges()); < ------------------ 

    view здесь представляет собой представление корневого компонента. Могут быть много корневых компонентов, как я описал в разделе Что такое последствия начальной загрузки нескольких компонентов .

    @milad описал причины, по которым вам потенциально может потребоваться автоматическое обнаружение изменений.

    markForCheck

    Как я уже сказал, этот парень вообще не вызывает обнаружение изменений. Он просто идет вверх от текущего компонента к корневому компоненту и обновляет свое состояние просмотра до ChecksEnabled . Вот исходный код:

     export function markParentViewsForCheck(view: ViewData) { let currView: ViewData|null = view; while (currView) { if (currView.def.flags & ViewFlags.OnPush) { currView.state |= ViewState.ChecksEnabled; < ----------------- } currView = currView.viewContainerParent || currView.parent; } } 

    Фактическое обнаружение изменений для компонента не запланировано, но когда это произойдет в будущем (либо в рамках текущего, либо следующего цикла CD), представления родительского компонента будут проверяться, даже если у них есть деблокированные детекторы изменений. Смена детектора может быть отключена либо с помощью cd.detach() либо путем определения страtagsи обнаружения изменений OnPush . Все собственные обработчики событий отмечают все представления родительских компонентов для проверки.

    Этот подход часто используется в ngDoCheck жизненного цикла ngDoCheck . Вы можете прочитать больше в разделе « Если вы считаете, что ngDoCheck означает, что ваш компонент проверяется - прочитайте эту статью .

    См. Также Все, что вам нужно знать об обнаружении изменений в Угловом для получения более подробной информации.

    Interesting Posts

    Конструкция конструктора по умолчанию и инициализация встроенного поля

    Как изменить десятичный разделитель DecimalFormat от запятой до точки / точки?

    Код форматирования с номерами строк

    Как инициализировать свойства, которые зависят друг от друга

    Слияние писем – несколько строк в один документ

    Как я могу сделать графики согласованной ширины в ggplot (с легендами)?

    Как читать двоичные данные через последовательный терминал в программе C?

    Невозможно удалить rEFInd на моем macbook pro

    Создавать диски восстановления, когда Windows 7 не загружается

    SSRS 2008 R2 – SSRS 2012 – ReportViewer: отчеты пусты в Safari и Chrome

    Windows не может загрузиться после установки «Switchable Graphics» в «Fixed Mode» на ноутбуке

    Различия между полной платформой Microsoft .NET 4.0 и профилем клиента

    Установите синтаксис по умолчанию для разных типов файлов в Sublime Text 2

    Программно включить Bluetooth в iphone sdk?

    Почему OS X использует swap, когда есть много «неактивной памяти»?

    Давайте будем гением компьютера.