标签: angular-changedetection

我是否应该始终使用ChangeDetectionStrategy.OnPush

我应该始终ChangeDetectionStrategy.OnPush在组件中使用吗?

我总是听到OnPush它绝对令人惊讶,并解决了许多问题,加快了Angular应用的速度,甚至摆脱了NgZone。但是,如果是这样,为什么默认情况下不生成它ng g component

如果真是太神奇了,那我们应该一直使用它吗?

angular2-changedetection angular angular-changedetection

5
推荐指数
2
解决办法
517
查看次数

当我从 ChangeDetectorRef 调用 detach() 时,为什么会调用 ngDoCheck() ?

我正在阅读一些有关更改检测的文章,并且尝试使用 和 启用或禁用更改changeDetectorRef.detach()检测changeDetectorRef.reattach()

我还将该组件挂接到唯一ngDoCheck()发现ngDoCheck()即使在之后也被调用detach()。我究竟做错了什么 ?有人可以解释为什么ngDocheck()被称为吗?我什至也有ChangeDetectionStartegy设置OnPush这是我正在阅读的文章以了解变更检测

我还为此创建了一个示例:https ://stackblitz.com/edit/angular-4ytdbs

observable angular angular-changedetection

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

Angular7-两次键入相同的值时,[ngModel]不会在组件中更新

最小的Stackblitz示例

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

在Angular 7 App中,我创建了一个带有<input>字段的简单组件。

当我使用键盘更改输入值时,我希望该值的格式设置为onBlur。-在最小的示例中,我只想向其中添加字符串“ EDIT”

这基本上是有效的:

  • 如果我输入“ test”并模糊该字段,它将更改为“ test EDIT”
  • 如果我输入“ lala”并模糊该字段,它将更改为“ lala 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

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

角度单击事件处理程序不触发更改检测

简而言之,我的问题是组件模板中有一个元素。该元素有一个ngIf条件和一个(click)处理程序。它不会从一开始就渲染,因为 ngIf 条件的计算结果为false

现在有趣的部分来了:在角度区域之外运行的代码将该条件更改为true,并且在detectChanges手动执行更改检测器引用后,该元素将被渲染,并且单击处理程序 ofc 将变为活动状态。

到目前为止,一切似乎都正常,但问题是,当(click)用户单击回调时,不会触发组件的更改检测。

这是复制品https://stackblitz.com/edit/angular-kea4wi

在那里重现它的步骤:

  1. 单击米色区域
  2. 出现按钮,也单击它
  3. 尽管消息应该出现在下面,但什么也没发生

描述:

  1. 米色区域有一个通过 addEventListener 注册的点击事件处理程序,并且该事件监听器的回调在角度区域之外运行。在其中,组件的showButton属性设置为从falsetrue,我通过调用 手动触发更改检测detectChanges(),否则属性中的更改showButton将不会被注册。代码如下所示:

    this.zone.runOutsideAngular(() => {
       const el = this.eventTarget.nativeElement as HTMLElement;
       el.addEventListener('click', e => {
         this.showButton = true;
         this.cd.detectChanges();
       })
     })
    
    Run Code Online (Sandbox Code Playgroud)
  2. 现在按钮出现了,这要归功于*ngIf="showButton"最初没有渲染,并且它在模板中声明了一个单击事件处理程序。该处理程序再次更改组件的属性,这次showMessage更改为true.

    <button *ngIf="showButton" (click)="onButtonClick()">Click me!</button>
    
    onButtonClick() {
      this.showMessage = true; …
    Run Code Online (Sandbox Code Playgroud)

javascript angular angular-changedetection

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

为什么 Angular 异步管道使用 cdr.markForCheck() 而不是 cdr.detectChanges()?

我有一个一般性的角度问题:

为什么async使用角管cdr.markForCheck()而不是cdr.detectChanges()

我认为这两种“风格”有两个主要区别:

  1. markForCheck()标记要检查的路径直到根组件 -要更新的内容
  2. markForCheck()让变化检测发生在当前或下一个周期 -计时

我的想法或问题:

  1. 为什么我们需要检查根的整个路径(在async管道中)?为什么不只是当前组件?( ) - 这与要更新的内容detectChanges()有关

  2. 为什么只标记(对于当前/下一个周期 - 使用markForCheck()ngZone)?为什么不立即检测变化?( ) 这与时间detectChanges()有关

  3. 如果没有 ngZone 异步触发器/没有异步操作怎么办?那么视图更新不会发生吗?

  4. 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请不要解释每种方法的作用,因为我在文档中阅读了很多次,并且从角度来看我无法理解。对我来说,重要的是要知道更新内容时间安排的原因。

angular ngzone angular-changedetection angular-ngzone

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

更改后,Angular 8 值不会在视图中更新

我在 Angular 中有一个小组件,它有一个方法(目前)设置超时并更改变量的值。

import { Component, ChangeDetectionStrategy } from '@angular/core';

@Component({
  selector: 'my-component',
  templateUrl: './my-view.html',
  styleUrls: ['./my-view.scss'],
  changeDetection: ChangeDetectionStrategy.Default
})
export class MyComponent {

  status: boolean = false;

  changeStatus(): void {

    setTimeout(() => {
      this.status = true;
    }, 1500);
  }
}
Run Code Online (Sandbox Code Playgroud)

和 HTML

<div>
  <form #myForm="ngForm">
    <input name="code" type="text" class="form-control" [(ngModel)]="code" #codeInput="ngModel" required placeholder="Enter your code" />
  </form>
</div>

<div class="row">
  <div class="col-md-5" (click)="changeStatus()">
    <mat-icon aria-label="clear-all" *ngIf="!status">&#xe042;</mat-icon>
    <a>Change status</a>
  </div>
  <div class="col-md-7">
    <button type="button" class="btn-flat app-btn-flat">Cancel</button>
    <button type="button" class="btn app-btn" …
Run Code Online (Sandbox Code Playgroud)

javascript angular2-changedetection angular angular-changedetection angular8

4
推荐指数
2
解决办法
1万
查看次数

嵌入子项与 ng-content 子项的不同 ChangeDetectionStrategy.OnPush 行为

我正在调整应用程序的性能并遇到以下差异。请参阅stackblitz的实例。

带有后缀的组件-on-pushChangeDetectionStrategy.OnPush,而带有后缀的组件-default有默认策略。

我有两种方法,我将第一种方法命名为“embedded”,将第二种方法命名为“ng-content”。澄清如下。

根模板:

<h1>embedded</h1>
<app-embedded-on-push></app-embedded-on-push>

<h1>ng-content</h1>
<app-ng-content-on-push>
  <app-ng-content-default></app-ng-content-default>
</app-ng-content-on-push>
Run Code Online (Sandbox Code Playgroud)

其中app-embedded-on-pushs 模板只是“嵌入”app-embedded-default组件:

<app-embedded-default></app-embedded-default>
Run Code Online (Sandbox Code Playgroud)

另一方面,app-ng-content-on-pushs 模板app-ng-content-default使用以下方式投影组件ng-content

<ng-content></ng-content>
Run Code Online (Sandbox Code Playgroud)

请参阅 stackblitz 以获得更好的想法。

期待

由于仅在输入引用发生更改时才检查组件ChangeDetectionStrategy.OnPush(组件本身及其子组件),因此我的期望是,在组件本身及其子组件上,这两种方法都不会触发更改检测,称为嵌入和内容投影方法。

现实

使用嵌入式方法,行为符合预期,app-embedded-default不会触发更改检测。另一方面,使用内容投影 ( ) 时,ng-content触发的子组件的更改检测,如上面的 stackblitz 中所示。app-ng-content-on-push

有人可以解释为什么这是结果行为吗?两种方法的组件树是相同的,还是我错了?

angular angular-changedetection

3
推荐指数
1
解决办法
1270
查看次数

Angular OnPush 不更新模板

我有两个组件,它们都设置为OnPush. 父组件集accountLoading为true,一旦getAccount()被调用,然后设置accountLoading为false,一旦完成呼叫。正如预期的那样,控制台输出:

this.accountLoading 真

其次是:

this.accountLoading 假

然而模板没有更新,并且一直认为这accountLoading是真的。当值发生变化时,如何让模板按预期更新?我想将更改检测保留为 OnPush。

父组件:

打字稿:

public accountLoading: boolean;
...

getAccount() {
  this.accountLoading = true;
    this.authStore
        .pipe(select(fromAuthStore.getAccountData))
        .subscribe(account => {
          if (account) {
            this.accountLoading = false;
          }
          console.log('this.accountLoading', this.accountLoading);
        });

  // Loading account if it hasn't yet been loaded
  this.authService.getAccount();
}
Run Code Online (Sandbox Code Playgroud)

HTML:

<child-component
  [accountLoading]="accountLoading">
</child-component>
Run Code Online (Sandbox Code Playgroud)

子组件

打字稿:

@Input() accountLoading: boolean;
...
Run Code Online (Sandbox Code Playgroud)

HTML:

<p *ngIf="accountLoading">
  Loading...
</p>
Run Code Online (Sandbox Code Playgroud)

angular angular-changedetection

3
推荐指数
1
解决办法
1739
查看次数

ExpressionChangedAfterItHasBeenCheckedError:在 HTTP 加载拦截器中检查后表达式已更改

目标:

我试图在每个 ajax 调用上显示一个加载图标。为此,我添加了一个 HTTP 拦截器,该拦截器在一个或多个请求正在进行时将变量设置为 true,在所有请求完成时将变量设置为 false。UI 会测试该值并显示是否显示加载程序,具体取决于。

问题:

每次 ajax 调用时,都会引发错误:

ExpressionChangedAfterItHasBeenCheckedError: 
Expression has changed after it was checked. 
Previous value: 'ngIf: [object Object]'. Current value: 'ngIf: true'.
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

具有可重现错误的简化 Stakckblitz:

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

代码:

应用程序组件.html:

<p *ngIf="loaderService.isLoading | async">
  Loading!
</p>
<p *ngIf="!(loaderService.isLoading | async)">
  Not Loading!
</p>
<button (click)="loadSomething()">Load Something</button>
{{matches|async}}
Run Code Online (Sandbox Code Playgroud)

应用程序组件.ts:

import { Component } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { LoaderService } from "./core";
import { Observable } from "rxjs";

@Component({
  selector: "my-app", …
Run Code Online (Sandbox Code Playgroud)

angular-http-interceptors angular-changedetection angular8

3
推荐指数
1
解决办法
1314
查看次数

Angular ChangeDetectorRef:无法读取未定义的属性“detectChanges”

我在 ChangeDetectorRef 中收到以下错误。当其他组件使用 ChangeDetectorRef 时,不知道为什么它突然发生。有谁知道如何解决?它链接到 Kendo Grid 选择。

类型错误:无法读取未定义的属性“detectChanges”

export class DocumentPropertyGridComponent implements OnInit, OnChanges {

  public documentPropertyGridDataSelected: Array<DocumentPropertyGridData> = new Array<DocumentPropertyGridData>();

  constructor(private cdr: ChangeDetectorRef) { 
  }

  selectTest(e){
    this.documentPropertyGridDataSelected = e.selectedRows;
    this.cdr.detectChanges();
  }
Run Code Online (Sandbox Code Playgroud)

HTML:

<div>
  Selected Count: {{documentPropertyGridDataSelected.length}}
<div>
Run Code Online (Sandbox Code Playgroud)

typescript angular angular-changedetection angular8

3
推荐指数
1
解决办法
6243
查看次数