当变量在订阅中发生变化时,为什么视图没有更新?
我有这个代码:
example.component.ts
testVariable: string;
ngOnInit() {
this.testVariable = 'foo';
this.someService.someObservable.subscribe(
() => console.log('success'),
(error) => console.log('error', error),
() => {
this.testVariable += '-bar';
console.log('completed', this.testVariable);
// prints: foo-Hello-bar
}
);
this.testVariable += '-Hello';
}
Run Code Online (Sandbox Code Playgroud)
example.component.html
{{testVariable}}
Run Code Online (Sandbox Code Playgroud)
但视图显示:foo-Hello.
为什么不显示:foo-Hello-bar?
如果我ChangeDetectorRef.detectChanges()在订阅中调用它将显示正确的值,但为什么我必须这样做?
我不应该从每个订阅中调用此方法,或者根本不应该(angular应该处理这个).有正确的方法吗?
我是否遗漏了Angular/rxjs 5到6的更新内容?
现在我有Angular版本6.0.2和rxjs 6.0.0.相同的代码在Angular 5.2和rxjs 5.5.10中正常工作,无需调用detectChanges.
使用Angular2(rc1),是否有人知道如何将默认的更改检测策略设置为OnPush?它可以以某种方式全局设置吗?
我想避免将此行添加到每个组件
@Component({
...
changeDetection: ChangeDetectionStrategy.OnPush,
...
})
Run Code Online (Sandbox Code Playgroud) 似乎在模板中使用 getter 会导致 Angular 更改检测进入循环(getter 被调用数百次)。在阅读了大量关于类似问题的文章后,我似乎无法得到明确的答案。
背景资料:
从可维护性的角度来看,我确实相信在模板中使用 getter 是最干净的方法,但似乎是因为 Angular 在调用它之前无法知道 getter 值是否改变,它只是一直调用它。到目前为止,我发现了三个替代方案:
选项 1 似乎有悖于使用 Typescript 类的好处。选项 2 看起来像是不必要的代码重复并降低了可维护性,选项 3 将需要大量重构。
这是一个示例(出于说明目的而简化)
模型:
export class UserModel {
private id: string;
get getId() {
console.log('Getting id');
return this.id;
}
set setId(id) {
this.id = id;
}
constructor() {
}
}
Run Code Online (Sandbox Code Playgroud)
组件.html
<h1>Test</h1>
<p>{{user.getId}}</p>
Run Code Online (Sandbox Code Playgroud)
组件.ts
import {Component, OnInit} from '@angular/core';
import {TestModel} from './test.model';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export …Run Code Online (Sandbox Code Playgroud) 我非常了解 Angular 的更改检测是如何工作的,以及我们如何使用 OnChanges 钩子来检测@Input属性更改,以及订阅 ngModel valueChanges 例如指令或组件等。
任何人都可以解释这里发生了什么:
# 自定义指令:
假设我们有一个自定义指令 myNumber,它有一个 @Input() 属性 ngModel:
@Directive({
selector: "[myNumber]"
})
class MyNumberDirective implements OnChanges {
@Input() ngModel: any;
constructor(private model: NgModel) {
this.model.control.valueChanges.subscribe(data => {
console.log('directive model changes detected by model control value change subscription');
});
}
ngOnChanges(changes: SimpleChanges){
if(changes.ngModel){
console.log('directive input ngModel changes detected by OnChanges hook');
}
}
}
Run Code Online (Sandbox Code Playgroud)
@Input属性 ngModel 和指令的模型对象更改。当模型值更改时,应将更改记录在控制台中。# 组件模板:
<input type="number" myNumber [(ngModel)]="number1" />
<input type="number" myNumber [(ngModel)]="number2" /> …Run Code Online (Sandbox Code Playgroud) 我正在尝试将应用程序迁移到使用ChangeDetectionStrategy.OnPush. 然而,我在尝试使用一些反应形式时遇到了一些阻碍。
我有一个可重用的控件,可以根据某些状态标志(例如*ngIf="control.touched && control.invalid")显示验证消息。我遇到的问题是,无法检测touched标志何时更改,因此无法使用ChangeDetectorRef.
可以通过侦听事件来引用输入元素本身来完成,click但这并不能说明何时markAsTouched()使用,并且传递对元素的引用并不总是可行的,而且总是不优雅。
有没有一种方法可以使用OnPush并仍然响应表单控件状态(例如touched),或者只是通常很痛苦?
angular2-changedetection angular angular-reactive-forms angular-changedetection
使用角度 10
\nSO 上有很多与此类似的问题,但我还没有找到一个可以回答我的情况的问题。
\n我希望有人能指导我。
\n我正在使用第三方库来显示 360\xc2\xb0 照片。这个第三方库有一个内置的API来显示场景中的热点。只需向库提供您想要成为热点的元素,它就会处理其余的事情。
\n我的大部分内容都按预期工作,但有一些部分没有按预期工作。
\n到目前为止,我正在动态生成我的组件,如下所示:
\nthis._hotspotFactory = this.resolver.resolveComponentFactory(HotspotComponent);\nconst component = this._hotspotFactory.create(this.injector);\n\n//Hydrate component with bunch of data\ncomponent.instance.id = data.id;\n...\n\n// Create the Hotspot with Third Party\n// Calling this third party method injects the native element into the DOM. \n// Passing the nativeElement in. Looks great at first glance. \nconst hotspot = this._scene.createHotspot(data, component.location.nativeElement);\n\nthis.appRef.attachView(component.hostView);\ncomponent.hostView.detectChanges();\n\nif(component.instance.over.observers.length) {\n hotspot.on(\'over\', (evt) => {\n this.zone.run(() => {\n component.instance.over.emit(evt);\n });\n });\n}\n\nif(component.instance.out.observers.length) {\n hotspot.on(\'out\', (evt) => {\n this.zone.run(() => …Run Code Online (Sandbox Code Playgroud) 我将从我在 StackOverflow 上看到一个类似问题的概念开始这个问题,但那个问题只回答了差异。
我要问的是我应该根据情况使用什么以及一种或另一种方法可能有哪些缺点。
我知道detectChanges在一个元素及其子元素上运行即时更改检测周期,同时markForCheck只将当前元素及其祖先标记为脏,并且应该在下一个更改检测周期中检查它们。
我问这个主要是因为我觉得我不应该总是markForCheck在异步调用中使用。
例如,我有一个InputComponent它是常规 HTML 输入的包装器。这InputComponent已ChangeDetectionStrategy.OnPush启用。
当我对服务器进行异步调用并获取数据时,我需要对其运行更改检测InputComponent以更新选项列表,我有两个选项。
首先(我觉得我应该使用的)是detectChanges因为它只会对这个确切的组件应用检查,同时markForCheck会导致检查整个树枝。
那么我应该使用什么,我需要使用markForCheck什么,为什么?
我有一个父组件和一个子组件。如果子组件在内部更新其值,我无法从父组件更新回值。
请参阅此 Stackblitz 中的示例:https ://stackblitz.com/edit/angular-ivy-tynepp 。当子组件失去焦点时,我会触发一个事件,父组件会重置子组件的值。但我认为,因为父级的“this.value”没有改变,所以更新不会触发子级的检测更改。
我该如何解决这个困境?
我一直在阅读一些有关变更检测策略的文章,但我对哪些情况下使用推送策略有意义存在一些疑问。基本上我的疑问是当我们嵌套组件时绑定的对象不是不可变的。我有两个嵌套组件,一个父组件和一个子组件,两者都具有推送时的更改检测策略。我将 formGroup 作为输入传递给子组件。
当我将表单设置为在父组件上启用,然后调用 ChangeDetectorRef.detectChanges() (它应该检查更改检测器及其子组件)时,我没有看到子组件上的更改(例如子组件上的 ngIf启用表单时显示内容)。
我做错了什么或者没有很好地理解?
我的应用程序组件正在订阅商店选择。我设置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 ×9
angular6 ×2
typescript ×2
angular5 ×1
components ×1
immutability ×1
javascript ×1
loops ×1
ngrx ×1
observable ×1
performance ×1
rxjs6 ×1
subscribe ×1