标签: angular-changedetection

绑定到函数时如何触发角度变化检测?

从这两个帖子:

我了解在"更改检测"发生时DOM是如何更新的.我从"你需要了解的关于Angular中的变化检测的所有内容"中不了解的是Angular如何跟踪函数内部使用的属性,以及何时运行"更改检测".

我们假设这是父组件视图.

<child [prop]="func()"></child>
Run Code Online (Sandbox Code Playgroud)

这里func()

func() { return this.parentProp }
Run Code Online (Sandbox Code Playgroud)

并且parentProp尚未在模板中使用.如果parentProp服务改变了,Angular如何知道func()依赖于什么parentProp,因此应该触发"更改检测"并更新视图.

angular angular-changedetection

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

仅运行一次 Angular 更改检测并停止检测该组件的更改

我只需要在加载组件或路由发生变化时检测一次角度变化,然后我想停止检测变化。

实际上我需要根据用户角色显示和隐藏功能。所以我*ngIf在一个 html 模板中有很多,但是我只需要在*ngIf第一次加载模板时检查一次条件,然后停止检测更改,因为它会影响性能。

我希望页面在单次更改检测后像静态一样。

例如 :

       <li *ngIf="doesHavePermission('templateName')">
       </li>
Run Code Online (Sandbox Code Playgroud)

应该检查一次,但我看到的是它正在多次检查单身的变化*ngIf,我有很多*ngIf这样的:

我发现markForCheck()detach()这个角文档中https://angular.io/api/core/ChangeDetectorRef

但他们正在做的是他们要么允许所有更改检测,要么根本不允许,

而且我只需要检测一次更改并在此之后停止。

我们可以在角度上进行单次时间变化检测吗?

或者有更好的方法来处理场景吗?

performance typescript angular2-changedetection angular angular-changedetection

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

角度变化检测:如何仅刷新某些项目?

假设我在屏幕上产生了100个div,*ngFor该div的值来自对象的数据,例如

{A1: someObject, A2: someOtherObject..., J10: someOtherOtherObject}

我单击A1,然后单击J10,它们切换其值。改为:

{A1: someOtherOtherObject, A2: someOtherObject..., J10: someObject}

如何强制Angular仅刷新仅包含A1和J10值的两个div?我正在使用ChangeDetectionStrategy.OnPush,在拥有的构造函数中cd.detach(),只有cd.detectChanges()在第二次单击发生时才调用。从我所看到和能够理解的角度来看,每个div都会触发它们,*ngIf因此将重新创建每个div 。

我可以做些什么来要么a)覆盖正在刷新的内容,要么b)选择检测更改所针对的内容?

在此处输入图片说明

angular2-changedetection angular angular-changedetection angular7

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

使用Moment.js自动更新相对时间的显示

给定项目列表(将其视为与多条消息聊天),我想使用来显示每个项目的相对时间(例如,自创建以来)。

每个项目都有其自己的组成部分,并且使用以下代码显示相对时间:

get timeFromNow(): string {
  return moment(this.pageLoaded).fromNow(); // pageLoaded is a JS Date
}
Run Code Online (Sandbox Code Playgroud)

问题是该组件不会更新相对时间的显示,因为原始输入(pageLoaded在上面的示例中)不会更改。

我的问题是:是否有应对这种情况的最佳实践?目前,我正在使用markForCheckof ChangeDetectorRef触发重新渲染。但是,我不确定这是否是一种性能良好的方法。

我已经在Stackblitz上创建了一个简单的演示。在演示中,我使用上述内容markForCheck触发更新。

momentjs angular angular-changedetection

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

角度内插值未在订阅时更新

  • 角 6.0.1
  • ngRx 6.0.1

我在我的视图中设置了一个内插值:

{{firstName}}

当它绑定到的字段的值发生变化时,它不会更新。但是,该值正在更改 - 如果我将其注销到订阅内的控制台,我会看到更新后的值。它只是不会在 UI 中更新。

这是相关的代码:

从我的组件订阅:

private subscribeToCurrentPerson(): void {
    this.tState$ = this.store
      .pipe(select(selectors.getCurrentPerson), takeWhile(() => this.componentActive))
      .subscribe((cp: Person) => {
        if (cp) {
          const name: string = cp.primaryName.value.parsedValue.givenNames[0];
          this.firstName = name;
          console.log('name: ' + name);  // <-- this shows correct new value
        }
  });
}
Run Code Online (Sandbox Code Playgroud)

subscribeToCurrentPerson从组件的 ngOnInit 调用。在此之前,该firstName属性是未定义的。

selectors.getCurrentPerson选择是这样的:

export const getCurrentPerson: MemoizedSelector<{}, Person> = 
    createSelector(getTState, (tState: ITState) => {
      console.log('selector: ', tState); // <-- …
Run Code Online (Sandbox Code Playgroud)

ngrx angular angular-changedetection

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

ExpressionChangedAfterItHasBeenCheckedError:检查后表达式已更改 - 如何在可观察值更改后更新模板

我浏览了很多 SO 帖子,试图找到解决这个问题的方法,我发现唯一一个有 hack 实现的帖子。我也有一个来自我订阅的 ngrx 商店的可观察对象:

this.navigationSelected$ = this.store.pipe(select(currentlySelectedNavigation));

this.navigationSelected$.subscribe(res => {
  ...
});
Run Code Online (Sandbox Code Playgroud)

使用 ngIf 取决于模板内的这个可观察值:

<profile-navigation *ngIf="(navigationSelected$ | async) == navigationLayout[0].location"></profile-navigation>
Run Code Online (Sandbox Code Playgroud)

每当 navigationSelected$ 的值发生变化时,就会抛出:

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

并且模板不会更新。我设法通过运行 cdRef.detectChanges(); 绕过它。在订阅结束时。它工作正常,但仍然抛出错误,而且如上所述,它似乎是一个黑客。

实现我想要做的事情的最佳方法是什么?

rxjs typescript angular angular-changedetection

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

仅在 Angular 7 中登录后才启用注销按钮

我引用了以下链接,仅在登录后启用注销按钮 https://stackblitz.com/edit/angular-login-hide-navbar-ngif

我只想在用户登录时在导航栏中显示“注销”,我通过从“身份验证服务”调用“this.authservice.isUserLoggedIn”并将其分配给变量并写入来验证用户是否已登录ngif“注销”链接附近的情况。我已经使用 BehaviourSubject 来获取当前状态。但我不知道为什么代码不起作用,它总是返回 false,因此即使用户登录后也不会启用“注销”链接

我有 header.component.ts

export class CommonheaderComponent implements OnInit {

  constructor(private authservice : AuthenticationService) { }
  isLoggedIn$ : Observable<boolean>;
  ngOnInit() {
    this.isLoggedIn$ = this.authservice.isUserLoggedIn;
  }
  }
Run Code Online (Sandbox Code Playgroud)

我有 header.component.html 如下

<ul class="nav navbar-nav">
      <li><a [routerLink]='["/search"]'>Search <span class="slider"></span></a></li>
      <li *ngIf="isLoggedIn"><a (click)="logout()">Logout</a></li>
  </ul>
Run Code Online (Sandbox Code Playgroud)

下面是login.component.ts

export class LoginComponent implements OnInit {
  isLoggedIn : Observable<boolean>;

 ngOnInit() {
   this.isLoggedIn = this.authservice.isUserLoggedIn;
   this.loginForm = this.formbuilder.group({
    username : ['', Validators.required],
    password : ['', Validators.required]
  })
 }

}

  onSubmit(){
    this.authservice.login(this.loginForm.value).subscribe(data => {
  }) …
Run Code Online (Sandbox Code Playgroud)

typescript behaviorsubject angular angular-changedetection angular7

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

修补表单时,控件的更改检测如何工作?

我想知道以下情况会发生什么:

我有一个带有这些控件的 formGroup:

{
  forename: new FormControl()
  surname: new FormControl()
}
Run Code Online (Sandbox Code Playgroud)

现在我像这样跟踪控件“姓氏”的变化(只是一个例子):

this.formGroup.get('surname').valueChanges.subscribe(changes => {
   if(this.formGroup.get('forename') == 'Max'){
      this.formGroup.get('forename').disable();
   }
})
Run Code Online (Sandbox Code Playgroud)

最后我像这样修补我的表单:

this.formGroup.patchForm({surname: 'Muster', forename: 'Max'});

控件“名字”会被禁用吗?因为我不确定它是否会在设置控件“名字”的值之前触发控件“姓氏”的更改。因此,“名字”可能还没有“正确”值。

我试图更好地理解,当触发确切的 valueChanges 事件时,因为我有时会遇到问题,但值没有设置,尽管它们应该设置。

我还想知道是否可以等到每个控件都修补完毕然后发出更改。

angular angular-reactive-forms angular-changedetection

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

更改子组件属性中的 @Input() 会阻止父组件的进一步更新

我有 2 个组件 - 父组件和子组件。请参阅stackblitz 演示 父级模板如下所示 - 在此输入图像描述

单击“显示子组件”时,isChild1Visible 设置为 true,导致子组件显示其模板。 在此输入图像描述

当您单击“隐藏我”时,子组件将 isVisible 设置为 false,从而使其被隐藏。现在,当再次单击“显示子组件”时,子组件将不会显示。

我在子组件中添加 ngOnChanges() 以查看更改检测,但是在初始化子组件时我看到以下内容: 在此输入图像描述

第一次点击“显示”后 在此输入图像描述

单击“隐藏我”后,即使稍后单击“显示我”,ngOnChanges()也不会打印任何内容。

那么,为什么在子组件中更新输入属性后更改检测停止工作?

angular angular-changedetection

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

从父组件更改时,Angular @Input 值不会更改

我在单个父组件中添加了相同的子组件三次 在此输入图像描述

下面是在一个子组件上调用的更改函数,以更改selectedName其他两个子组件中的@Input字符串类型,如果我将其更改为对象,它可以正常工作。

在此输入图像描述

这就是子组件的样子 在此输入图像描述

ngonchanges angular ngzone angular-changedetection

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

Angular - 如何不重建使用 *ng 创建的列表,任何时候触发列表的每个元素上的事件

我有一个简单的<div>生成 using*ngFor指令列表,类似于

<div *ngFor="let item of items() | async ; let i=index" 
  [ngClass]="getItemClass(i)"
  (click)="itemClick(i)"</div>
Run Code Online (Sandbox Code Playgroud)

如您所见,该方法返回的 Observable 每次items()发出时都会异步填充列表。在我的情况下,这样的 Observable 是 a ReplaySubject,如果这对知道有任何用处。然后我<div>使用方法定义要应用于每个元素的类getItemClass

我还想使用方法对每个项目上的点击事件做出反应itemClick(i: number)

问题

任何时候div单击一个元素,即任何时候itemClick(i: number)运行该方法,似乎<div>都重建了整个s列表。我得出这个结论是观察到任何时候div点击一个元素,该items()方法也会运行。

<div>单击其中一个元素时是否可以避免重建列表?我已经设置changeDetectionOnPush但它似乎并没有解决我的问题。

angular angular-changedetection

0
推荐指数
1
解决办法
1069
查看次数

子组件初始化后,父组件对子 DOM 的操作会导致 ExpressionChangedAfterItHasBeenCheckedError

我想在子组件初始化后从父组件对子组件进行一些操作。

家长:

export class ParentComponent implements AfterViewInit {
  @ViewChild('child') childComponent: ChildComponent;

  ngAfterViewInit() {
    this.childComponent.domMethod('boo');
  }
}
Run Code Online (Sandbox Code Playgroud)
<p>parent</p>

<app-child #child></app-child>
Run Code Online (Sandbox Code Playgroud)

孩子:

<p>parent</p>

<app-child #child></app-child>
Run Code Online (Sandbox Code Playgroud)
<p>child</p>

<input type="text" id="childInput" [(ngModel)]="term">

<ul>
    <li *ngFor="let item of items | search: term">{{item.name}}</li>
</ul>
Run Code Online (Sandbox Code Playgroud)

链接到StackBlitz以进行复制

编辑:

如果我添加setTimeout到父组件,它就可以工作。我可以在没有的情况下实现setTimeout吗?

export class ChildComponent implements OnInit {
  constructor(private readonly cdr: ChangeDetectorRef,) {

  }
  public term = '';
  public items;
  ngOnInit() {
    this.items = [
      { name: 'foo' },
      { name: 'bar' },
      { name: …
Run Code Online (Sandbox Code Playgroud)

angular angular-changedetection

0
推荐指数
1
解决办法
814
查看次数