Реальные варианты использования ngDoCheck (Angular9)

Я новичок в Angular и учусь сам, и я застрял в методе жизненного цикла ngDoCheck

Согласно документации:
обнаруживать и действовать в соответствии с изменениями, которые Angular не может или не может обнаружить самостоятельно.

Родительский компонент:

user={
   name:"xxx"
}

update(){
  this.user.name="yyy"
}

Родительский вид:

<button (click)="update">update</button>
<child-comp [inputprop]="user"></child-comp>

Дочерний компонент

ngDoCheck(){
console.log(this.inputprop);
}

Насколько мне известно, использование этого метода жизненного цикла для получения последних изменений на более глубоком уровне, что ngOnChanges не может обнаружить изменения свойств ввода на более глубоком уровне.

Проще говоря,ngOnChanges обнаружит изменения свойств, только если ссылка на свойство изменится.

В приведенном выше примере метод жизненного цикла ngDocheck ничего не делает для получения последних изменений свойств. Но вместо этого обнаружение изменений помогает получить последние изменения на более глубоком уровне.

Я хочу знать точный вариант использования метода жизненного цикла ngDoCheck.

2 ответа

Решение

Детектор изменения дочернего компонента может иметь следующие стратегии

  1. дефолт
  2. onPush

В стратегии по умолчанию CD запускается при любом изменении в свойствах @Input().

В стратегии onPush CD запускается, когда вы передаете новый объект (ссылку) в оформленные свойства @Input.

Независимо от стратегии, CD всегда запускается в следующих сценариях:

  1. Запускается такое событие, как click, submit.
  2. Вызов XHR для работы с API
  3. Выполняются асинхронные функции JavaScript, такие как assetTimeOut() или setInterval()

Имейте в виду, что Angular CD может быть визуализирован как направленное дерево, что означает, что все компоненты можно рассматривать как узел в дереве, а Angular всегда запускает CD от корневого узла до конца дерева.

Даже если в CC-121 происходит событие, Angular запускает CD от корневого компонента до самого низа. Однако запуск CD остановится на узле, где стратегия установлена ​​на onPush, и вы не передаете новый объект в одно из оформленных свойств @Input.

Итак, теперь вы немного понимаете, когда и как запускается CD, жизненный цикл ngDoCheck() выполняется каждый раз, когда CD запускается для компонента.

Я надеюсь, что это помогает.

Спасибо

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

В Angular мы можем выполнять обнаружение изменений, используя два разных хука жизненного цикла:

хук жизненного цикла ngOnchanges и хук жизненного цикла ngDoCheck .

Но в некоторых случаях ngOnChanges недостаточно для обнаружения всех изменений, поскольку он использует ссылку на свойство для проверки различий, поэтому он не может обнаружить изменения, если вы обновите свойство объекта.

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

Например, если вы передаете объект пользователя из родительского компонента, вы обновляете возраст или свойство имени пользователя объекта пользователя, в этом случае Angular не будет запускать событие для отправки обратного вызова ngOnChange. Потому что он имеет ту же ссылку на объект User.

Таким образом, вы можете решить эту проблему, используя хук жизненного цикла ngDoCheck .

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

проверьте этот небольшой пример:

        //child-component.ts
import {Component, DoCheck, Input, KeyValueDiffers, OnInit} from "@angular/core";

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
})
export class ChildComponent implements OnInit, DoCheck {

  @Input() user: any;

  changelogList: Array<string> = [];

  differ: any;

  constructor(private differs: KeyValueDiffers) {
  }

  ngOnInit() {
    this.differ = this.differs.find(this.user).create();
  }


  ngDoCheck() {
    const userChanges = this.differ.diff(this.user);
    if (userChanges) {
      userChanges.forEachChangedItem((changeRecord: any) => {
        this.changelogList.push('item changed : ' + changeRecord.key + ' ' + JSON.stringify(changeRecord.currentValue))
      });
      userChanges.forEachAddedItem((changeRecord: any) => {
        this.changelogList.push('item added : ' + changeRecord.key + ' ' + JSON.stringify(changeRecord.currentValue))
      });
    }
  }
}

метод Different внутри ngDoCheck возвращает объект un, который предоставляет несколько расширенных методов, таких как

forEachItem , forEachPreviousItem , forEachChangedItem , forEachAddedItem , forEachRemovedItem.

Другие вопросы по тегам