我的应用程序组件正在订阅商店选择。我设置ChangeDetectionStrategy为OnPush. 我一直在阅读有关这是如何工作的;需要更新对象引用才能触发更改。然而,当您使用异步管道时,Angular 会期待新的可观察更改并为您执行 MarkForCheck。MarkForCheck那么,当触发订阅并设置channels$新的可观察通道数组时,为什么我的代码不渲染通道(除非我调用)。
@Component({
selector: 'podcast-search',
changeDetection: ChangeDetectionStrategy.OnPush, // turn this off if you want everything handled by NGRX. No watches. NgModel wont work
template: `
<h1>Podcasts Search</h1>
<div>
<input name="searchValue" type="text" [(ngModel)]="searchValue" ><button type="submit" (click)="doSearch()">Search</button>
</div>
<hr>
<div *ngIf="showChannels">
<h2>Found the following channels</h2>
<div *ngFor="let channel of channels$ | async" (click)="loadChannel( channel )">{{channel.trackName}}</div>
</div>
`,
})
export class PodcastSearchComponent implements OnInit {
channels$: Observable<Channel[]>;
searchValue: string;
showChannels = false;
test: …Run Code Online (Sandbox Code Playgroud) 我们的Angular应用程序中有许多组件需要定期显示每个组件唯一的新值(倒计时,时间戳,已用时间等).最自然的方法是创建使用RxJS timer和interval工厂函数的observable .但是,这些会在调用间隔函数时多次触发整个应用程序的每个间隔的角度变化检测.如果我们在页面上有许多组件,则会触发每秒或每个时间段对整个应用程序进行数十次检测,从而产生很大的性能开销.
到目前为止,我有两种尝试解决问题的方法.对这两者的一个好的答案将是非常有帮助的 - 理想的是两者.我想避免手动触发变化检测,而是依赖于Observables发出的新值,并让异步管道/ OnPush变化检测策略负责触发变化检测.如果这是不可能的,我想了解原因.
timer或interval函数触发角度变化检测?使用NgZone zone.runOutsideAngular(() => this.interval$ = interval(1000) ... )似乎不会这样做.StackBlitz示例:https://stackblitz.com/edit/angular-zo5h39Subject结合setInterval被调用的内部创建一个Observable流zone.runOutsideAngular,为什么在从主题发出新值时不会为子组件触发更改检测?StackBlitz示例:https://stackblitz.com/edit/angular-yxdjgd我创建了一个简单的示例来演示我面临的一个奇怪问题。
Stackblitz- https: //stackblitz.com/edit/angular-change-detection-form-group
我有三个组成部分,它们是:
1-应用程序组件
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
@Component({
selector: 'my-app',
template: `<hello [form]="form"></hello>
<hr />
<button (click)="changeFormValue()">Change Form Value</button>`,
styleUrls: ['./app.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent implements OnInit {
name = 'Angular';
form: FormGroup;
ngOnInit() {
this.form = new FormGroup({
name: new FormControl('ABC'),
age: new FormControl('24')
});
}
changeFormValue() {
this.form.setValue({
name: 'XYZ',
age: 35
})
}
}
Run Code Online (Sandbox Code Playgroud)
2-Hello组件
import { Component, Input, OnChanges, ChangeDetectionStrategy …Run Code Online (Sandbox Code Playgroud) 到处都说 markForCheck 只是将当前组件视图和所有父组件(直到根组件)标记为脏组件。因此下次执行 DetectChanges 时它将更新视图。从这一点上我有两个问题。两者都在该组件具有的上下文中changeDetection: ChangeDetectionStrategy.OnPush
1)如果“async pipeline”除了调用markForCheck(源代码)什么都不做,为什么视图会更新?
2)如果我尝试在某个异步进程中调用markForCheck,视图也会更新。
演示:stackblitz
您能帮助我了解这些过程中发生的情况以及视图实际更新的原因吗?我期待有人在 1) 和 2) 之后调用 DetectChanges 方法,但是谁......
我应该始终ChangeDetectionStrategy.OnPush在组件中使用吗?
我总是听到OnPush它绝对令人惊讶,并解决了许多问题,加快了Angular应用的速度,甚至摆脱了NgZone。但是,如果是这样,为什么默认情况下不生成它ng g component?
如果真是太神奇了,那我们应该一直使用它吗?
我正在阅读一些有关更改检测的文章,并且尝试使用 和 启用或禁用更改changeDetectorRef.detach()检测changeDetectorRef.reattach()。
我还将该组件挂接到唯一ngDoCheck()发现ngDoCheck()即使在之后也被调用detach()。我究竟做错了什么 ?有人可以解释为什么ngDocheck()被称为吗?我什至也有ChangeDetectionStartegy设置OnPush。
这是我正在阅读的文章以了解变更检测
我还为此创建了一个示例:https ://stackblitz.com/edit/angular-4ytdbs
https://stackblitz.com/edit/angular-mqqvz1
在Angular 7 App中,我创建了一个带有<input>字段的简单组件。
当我使用键盘更改输入值时,我希望该值的格式设置为onBlur。-在最小的示例中,我只想向其中添加字符串“ EDIT”。
这基本上是有效的:
但是, 当我键入“测试”-模糊(有效)并再次键入“测试”时,它将不再起作用!
该onInputUpdate()功能全被调用(你可以看到它在控制台日志),变量inputValue被更新(你可以看到它的组件{{inputValue}}),但是输入值不会改变!
我希望它是“测试编辑”,但它保持“测试”。
当我键入另一个字符串时,它可以工作,但是连续两次在同一字符串中输入却不起作用。这是为什么?我怎样才能解决这个问题?
component.html
{{inputValue}} <br />
<input type="text"
[ngModel]="inputValue"
(ngModelChange)="onInputUpdate($event)"
[ngModelOptions]="{ updateOn: 'blur' }"/>
Run Code Online (Sandbox Code Playgroud)
component.ts
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {
inputValue = "teststring";
constructor(
private changeDetectorRef: ChangeDetectorRef,
) {}
public ngOnInit() {
this.inputValue = "initial";
}
public onInputUpdate(inputValue: string) …Run Code Online (Sandbox Code Playgroud) angular-ngmodel angular-components angular angular-changedetection angular7
我在使用 Angular 6 应用程序时遇到问题:
假设我有 2 个组件:父组件和子组件。
孩子有2个输入。当 1 个输入发生变化时,在 ngOnChanges() 中,子组件向父组件发出一些东西。
然后父组件更改子组件的第二个输入。我希望再次调用子组件的更改检测 - 但事实并非如此。子组件的视图显示了第二个输入的旧值。
该申请有以下定义:
为了说明这个案例,我创建了一个简单的演示项目。在那里我不使用商店,所以我没有任何选择器......相反,我使用 rxjs Subject 来使用异步管道。
这里是:
https://angular-ccejq4.stackblitz.io
查看控制台以了解会发生什么以及何时发生。
我已经尝试过的:
我发现新值到达异步管道。然后异步管道调用 markForCheck()。但它不会调用detectChanges()..所以更改检测周期不会运行。视图只会在下一个更改检测周期时正确更改 - 正如您在我的演示应用程序中看到的那样。
有任何想法吗?
谢谢!
rxjs ngrx angular2-changedetection angular angular-changedetection
我有一个一般性的角度问题:
为什么async使用角管cdr.markForCheck()而不是cdr.detectChanges()?
我认为这两种“风格”有两个主要区别:
markForCheck()标记要检查的路径直到根组件 -要更新的内容markForCheck()让变化检测发生在当前或下一个周期 -计时我的想法或问题:
为什么我们需要检查根的整个路径(在async管道中)?为什么不只是当前组件?( ) - 这与要更新的内容detectChanges()有关
为什么只标记(对于当前/下一个周期 - 使用markForCheck()ngZone)?为什么不立即检测变化?( ) 这与时间detectChanges()有关
如果没有 ngZone 异步触发器/没有异步操作怎么办?那么视图更新不会发生吗?
async如果我们改为使用管道会发生什么detectChanges()?
异步管道:
private _updateLatestValue(async: any, value: Object): void {
if (async === this._obj) {
this._latestValue = value;
this._ref.markForCheck();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:
async请不要解释每种方法的作用,因为我在文档中阅读了很多次,并且从角度来看我无法理解。对我来说,重要的是要知道更新内容和时间安排的原因。