标签: angular2-changedetection

Angular2 模板表达式在更改检测时为每个组件调用两次

相当标准的情况。

有一个父组件<item-list>。在其模板内*ngFor生成了 20 个子组件<item-block>[ngStyle]使用调用 function 的指令和模板表达式设置子组件样式setStyles()

问题(或可能不是)是,当在一个特定子元素上发出任何事件时,表达式setStyles()会对每个子组件执行两次。

因此,如果我们单击示例中的一个特定项目,并且我们有 20 个<item-block>组件 -setStyles()将执行 20+20 次。

问题是

  1. 为什么会发生这种情况以及这是预期的行为吗?
  2. 它如何影响性能
  3. 如何避免这种情况 - 每个子组件/检测更改仅调用一次。

示例&plnkr

plnkr(单击项目 - 打开控制台以进行调试输出)

import {Component} from '@angular/core'

@Component({
  selector: 'item-list',
  template: `
    <item-block
        [item]="item"
        *ngFor="let item of items"
    ></item-block>
  `,
})
export class ItemListComponent {

  items: any[] = [];

  constructor() {}

  ngOnInit() {
     // generate dummy empty items
    for (let i = …
Run Code Online (Sandbox Code Playgroud)

angular2-template angular2-changedetection angular2-components angular

5
推荐指数
1
解决办法
1685
查看次数

为什么替换对象不会触发 Angular2 中的更改检测?

我通过服务将对象数组共享给我的组件。因此,有一刻我想用新对象的属性替换数组对象的属性之一(我替换该对象)。因此,我的共享对象应该在使用它的所有模板中更新。

https://plnkr.co/edit/0sRxSivEaEPLsNAJo7MV?p=preview

// my.component.ts
@Component({ 
selector: 'my-component',
template: '<div>MyComponent: {{item.name}}</div>',
})
export class MyComponent implements OnInit {
  constructor(private myService: MyService) {}

  private item = myService.myListData[0];

  ngOnInit() {
    // 1. - This triggers change detection in app.ts template
    this.item.name = 'Name 1111';

    setTimeout(() => {
      // 2. - This doesn't trigger change detection in app.ts template
      let newObj = {name: 'Name 222', age: 225};
      this.item = newObj;
    }, 3000);
  }
}
Run Code Online (Sandbox Code Playgroud)

在我的例子中 //1 更改 app.ts 和 my.component.ts 中的模板值,但 //2 仅在 my.component.ts …

angular2-changedetection angular

5
推荐指数
1
解决办法
3346
查看次数

Angular 2,从 Observable 内部发生变化检测不起作用

假设我必须跟随实体

export class Photo {
   public data: Blob;
   public User: string;
}
Run Code Online (Sandbox Code Playgroud)

以下组件

@Component({
   template: '<my-other-component [(ngModel)]="photo.data"></my-other-component>'
})
export class MyComponent {
    @Input()
    photo: Photo;

    constructor(private photoService: PhotoService, private cd: ChangeDetectorRef){}

    public deletePhoto(): void {
       this.photoService.deletePhoto(this.photo)
           .subscribe((result: ApiResult) => {

             //if done here, change detection doesn't work
            this.photo = new Photo();
           });

        //if done here, change detection works
        this.photo = new Photo();
   }
}
Run Code Online (Sandbox Code Playgroud)

PhotoService 是一个发出http 删除请求的服务。

my-other-component实施ControlValueAccessor

my-other-component每当我更改在方法中绑定到子组件的对象时subscribe,都不会传播任何更改。

如果我在我的方法之外调用它,subscribe它就会起作用并my-other-component收到有关更改的通知。

photo …

observable angular2-changedetection angular

5
推荐指数
0
解决办法
1642
查看次数

角度变化检测:为什么要检查整个树的局部变化?

假设我有一个简单的文本数组:

textContent = [
    {text: 'good morning'},
    {text: 'lovely day'},
    {text: 'for debugging'},
  ]
Run Code Online (Sandbox Code Playgroud)

我为每个组件渲染一个简单的组件,并传入文本项作为输入:

<app-text *ngFor="let text of textContent" [text]="text"></app-text>
Run Code Online (Sandbox Code Playgroud)

文本组件渲染文本,用ngModel:

<textarea [(ngModel)]="text.text"></textarea>
Run Code Online (Sandbox Code Playgroud)

我还登录了 DoCheck:

ngDoCheck() {
    console.log(this.text.text, ' has been checked')
}
Run Code Online (Sandbox Code Playgroud)

当我在一个文本区域中输入某些内容时,所有其他组件的 DoCheck 都会被触发。

good morning   has been checked
lovely days    has been checked
for debuggings has been checked
Run Code Online (Sandbox Code Playgroud)

即使使用 OnPush 进行更改检测,也会发生这种情况。

问题:为什么对一个组件的数据进行更改会触发检查整个树?

(对于少数组件来说这不是问题,但是对于较大的树,我会丢帧)。

我实际上注意到,即使是完全独立的内容树上的组件也会触发其“doCheck”。

有没有办法防止这种情况发生,或者我完全错过了其他东西?

angular2-changedetection angular

5
推荐指数
1
解决办法
978
查看次数

changeDetection:ChangeDetectionStrategy.OnPush 似乎不起作用?

https://stackblitz.com/edit/angular-xpamld

问题:有人可以帮助我理解为什么我的原型changeDetection: ChangeDetectionStrategy.OnPush仍然允许我更新内部值name吗?如果这不是ChangeDetectionStrategy.OnPush应该阻止的,它应该做什么?

app.component.ts:

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent  {
  public name = 'Angular 5';
  public changeName() {
    this.name = 'Outer';
  }
}
Run Code Online (Sandbox Code Playgroud)

app.component.html:

<hello name="{{ name }}"></hello>
<button (click)="changeName()">Outter Change</button>
<p>{{name}}-- outer</p>
<p>
  Start editing to see some magic happen :)
</p>
Run Code Online (Sandbox Code Playgroud)

你好.component.ts:

@Component({
  selector: 'hello',
  template: `<h1>Hello {{name}}!</h1> <button (click)="changeName()">inner Change</button>`,
  styles: [`h1 { font-family: Lato; }`],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export …
Run Code Online (Sandbox Code Playgroud)

angular2-changedetection angular

5
推荐指数
1
解决办法
6261
查看次数

Angular 为什么当 detectorChanges 也可以工作时我们需要 markForCheck

我正在阅读这篇文章,其中有一节介绍何时使用markForChange().

在他的示例中,他具有以下组件:

@Component({
  selector: 'cart-badge',
  template: '{{counter}}',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class CartBadgeComponent {

  @Input() addItemStream;

  counter = 0;

  constructor(private cd: ChangeDetectorRef) {}

  ngOnInit() {
    this.addItemStream.subscribe(() => {
      this.counter++;
      this.cd.markForCheck();
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

他使用该markForCheck()方法来更新视图。我不明白的是,为什么markForCheck()当调用detectChanges() 也更新视图时我们需要在这里使用?

我在 StackOverflow 上阅读了问题的答案 - MarkForCheck() 和 detectorChanges() 有什么区别?

但不符合上面的例子。那么,为什么不打电话detectChanges()markForCheck()

angular2-changedetection angular

5
推荐指数
1
解决办法
3843
查看次数

使用 OnPush 更改检测的最佳方法

使用OnPush变更检测来使变更灵活且在测试中也非常简单的最佳方法是什么?通过各种教程,我发现可以使用OnPush

  1. 首先是在视图中直接使用服务中的可观察对象,我不确定该方法是否有效。https://blog.angular-university.io/onpush-change-detection-how-it-works/
  2. 另一种选择是使用 immutable.js 但在这种情况下,我不知道创建对象是否非常灵活,我知道在列表的情况下更容易。

也许你知道不同的方法然后我列出的这个?

angular2-changedetection angular

5
推荐指数
1
解决办法
1651
查看次数

Angular 5 - 如何将更改检测仅限于组件范围?

如何配置 Angular 组件不触发整个应用程序的更改检测,而只触发组件本身及其子组件?

工作示例:https : //stackblitz.com/edit/angular-irc-starter-4txpbu?file=app%2Ftimer%2Ftimer.component.ts

有一个计数器每秒增加一个值。它是 TimerComponent 并且它按预期工作 - 每秒增加和更新值。

@Component({
  selector: 'app-timer',
  template: `{{value}}`
})
export class TimerComponent implements OnInit {
  value: number = 0;
  ngOnInit() {
    setInterval(() => this.value++, 1000);
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,请查看父组件 AppComponent。

<h3>Internal timer:</h3>
<p>Should not perform change detection for the whole app</p>
<app-timer></app-timer>

<h3>External binding</h3>
<p>Should not be updated after timer changes</p>
<p>{{someBindingProperty}}</p>
Run Code Online (Sandbox Code Playgroud)

someBindingProperty是一个吸气剂:

get someBindingProperty() {
  this.bindingTimer++;
  return this.bindingTimer;
}
Run Code Online (Sandbox Code Playgroud)

问题:当 TimerComponent 增加值时,会触发整个应用程序的更改检测。是否可以仅在组件和子组件内触发更改检测?

注意:如果我添加到 TimerComponent:

changeDetection: ChangeDetectionStrategy.OnPush
Run Code Online (Sandbox Code Playgroud)

然后在此组件中不会检测到更改,但仍会为整个应用程序触发更改检测。所以这不是一个解决方案。

javascript angular2-changedetection angular angular5

5
推荐指数
1
解决办法
1248
查看次数

使用 IterableDiffer 获取 Angular 8 中数组大小的变化

我有带有对象数组的角度分量

export class AlertsConfigListComponent implements OnInit, DoCheck {
@Input() config: ProductAlertConfig[];
Run Code Online (Sandbox Code Playgroud)

并使用 IterableDiffer 来获取该数组的更改: constructor(private iterableDiffers: IterableDiffers) { this.iterableDiffer = iterableDiffers.find([]).create(null); }

ngDoCheck(): void {
let changes : IterableChanges<ProductAlertConfig> = this.iterableDiffer.diff(this.config);
if (changes) {
  this.doSmth();
}
Run Code Online (Sandbox Code Playgroud)

}

它有效,每次更改数组时我都可以得到更改。所以现在我的问题是。如何检查数组大小已更改的更改对象,因为当我对此数组进行排序时也会触发它。IterableChanges对象中没有用于此目的的属性。

如果我可以获得新的数组大小,我会这样做:

ngDoCheck(): void {
let changes : IterableChanges<ProductAlertConfig> = this.iterableDiffer.diff(this.config);
if (changes && newSize !== oldSize) {
  this.doSmth();
}
Run Code Online (Sandbox Code Playgroud)

}

它可以解决问题,但是还有其他解决方案吗?

javascript iterable angular2-changedetection angular

5
推荐指数
1
解决办法
3171
查看次数

角度信号如何影响 RXJS Observables 以及在这种情况下检测会发生什么变化

我正在尝试在 Angular 应用程序中切换到信号,目前在寻找良好实践方面遇到问题,并且我也经历了(至少对我来说)意外的行为。

这是我的代码片段,由一个 userService 和两个组件组成

export class UserService {
  private user$: Observable<User>;
  private refreshUser$ = new BehaviorSubject<void>(undefined);

  constructor(private readonly http: HttpClient) {}

  getUser(): Observable<User> {
    if (!this.user$) {
      this.user$ = this.refreshUser$.pipe(
        switchMap(() => this.http.get<User>('...')),
        shareReplay(1)
      );
    }
    return this.user$;
  }

  reloadUser(): void {
    this.refreshUser$.next();
  }
}
Run Code Online (Sandbox Code Playgroud)

然后我有组件 A 为用户订阅:

export class aComponent {

 currentUser: User;

  constructor(private readonly userService: UserService) {
    this.userService.getUser().subscribe((user) => {
      this.currentUser = user;
    });
 }
}
Run Code Online (Sandbox Code Playgroud)

我有组件 aChild,它是组件 A 的子组件,也订阅用户并且还可以操作用户。它能够更改/删除用户的地址。在使用信号之前,我会立即更新组件的 currentUser 对象的地址,以便用户可以立即看到结果,并且我会从服务调用“reloadUser()”,以便全局用户是最新的,并且“A Component " 具有正确的值(这可能不是最好的解决方案,因为它会导致另一个 http …

rxjs angular2-changedetection angular angular-signals angular16

5
推荐指数
1
解决办法
1163
查看次数