#angular #typescript #iterator #yield
#угловой #typescript #итератор #выход
Вопрос:
У меня есть компонент с методом:
public *numGen(): Iterator<number> {
for (let i = 0; i < 5; i)
yield i;
}
и HTML с:
<p *ngFor="let n of numGen()">{{n}}</p>
Я ожидаю, что это сгенерирует:
<p>0</p>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
что он и делает, но при этом также генерируется ошибка:
ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.
Previous value: 'ngForOf: [object Generator]'. Current value: 'ngForOf: [object Generator]'.
Кто-нибудь знает, как предотвратить генерирование ошибки?
Ответ №1:
Один из способов — использовать OnPush
стратегию обнаружения изменений. Это гарантирует, что он проверяет привязки только тогда, когда что-то внутри компонента изменилось с помощью @Input
или события, отправленного из шаблона. Который сам по себе имеет значительное улучшение производительности и более логичную схему срабатывания обнаружения изменений.
@Component({
// ...
changeDetection: ChangeDetectionStrategy.OnPush
})
Причина, по которой вы видите эту ошибку, заключается в том, что ваш метод возвращает новую Generator
ссылку на объект при каждом обнаружении изменения.
Другим способом было бы устанавливать генератор только тогда, когда в вашем компоненте что-то меняется, что требует обновления генератора. Для этого вы могли бы использовать ngDoCheck
крючок. Имейте в виду, что это происходит довольно часто, хотя и не так часто, если вы используете OnPush
стратегию, которую я в любом случае настоятельно рекомендую.
export class AppComponent {
generator: Iterable<number> = this.numGen();
multiplier = 1;
ngDoCheck(): void {
this.generator = this.numGen();
}
times(): void {
this.multiplier *= 2;
}
private *numGen(): Iterable<number> {
for (let i = 0; i < 5; i) {
yield i * this.multiplier;
}
}
}
Мне действительно интересно, для какого варианта использования вы используете итератор / генератор?
Комментарии:
1. Ах! Я думал, что попробовал что-то похожее на подход ngOnChanges. Стратегия ChangeDetectionStrategy отлично работает.
2. Я не совсем уверен, нужно ли мне это использовать, но я просто экспериментировал, чтобы посмотреть, сработает ли это. В конечном итоге у меня есть 2D-массив, который я хотел бы иметь возможность просматривать иногда как набор столбцов, а иногда как набор строк. Использование итератора кажется проще, чем копирование содержимого в массивы для столбцов. Я должен отметить, что я думаю как программист C #.
3. @JasperKent Хорошо, тогда это имеет смысл 🙂 генераторы обычно не являются моим первым решением, просто когда производительность становится проблемой при работе с большими наборами данных, так что, возможно, вы имеете в виду правильный вариант использования!
4. @JasperKent Я немного обновил свой ответ, предложив решение для
ngOnChanges
🙂 (подождите, это, очевидно, не работает, игнорируйте это)5. @JasperKent хорошо: p теперь я нашел другой способ