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

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

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

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

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

    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

    Как реализованы windows чата facebook?

    Как использовать одновременные подключения vpn через Windows 7 и привязывать их к конкретной программе?

    Использование Boost для чтения и записи XML-файлов

    Синтаксис C для функций, возвращающих указатели функций

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

    byte поиск шаблона массива

    Как получить данные из базы данных sqlite в android и отобразить ее в TextView

    Что предназначено для распространения с обновленным компьютером?

    Как десериализовать XML-документ

    Как я могу узнать, что является узким местом, замедляющим определенный процесс / всю систему?

    Excel – как иметь прямой ввод данных или значение ячейки из формулы

    Как изменить исходный поиск Opera, выделяющий цвет?

    Не удалось запустить Windows XP, поскольку отсутствует или поврежден следующий файл: \ WINDOWS \ SYSTEM32 \ CONFIG \ SYSTEM

    Настройки удаленного рабочего стола отсутствуют

    Как я могу указать записи REG_EXPAND_SZ в файле .REG?

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