繁体   English   中英

使用硬编码对象数组时,Angular Material mat-button 在 *NgFor 中似乎不起作用

[英]Angular Material mat-button does not seem to work inside of *NgFor when working with an array of hardcoded objects

我在 Angular 工作了几年,遇到了一些奇怪的事情。 我不确定这是否是版本的一个奇怪的 Angular 问题,或者我从未遇到过这个特定问题。 我还在一个新的 Angular 应用程序中尝试了这个,以保持理智,但问题似乎仍然存在。

本质上,我创建了一个 getter 来返回一个硬编码的对象数组。 然后我遍历模板中的对象以显示它们的数据并为每个项目创建一个按钮。 现在,当我不使用MatButtonModule mat-button ,按钮将按预期工作。 但是,当我使用mat-button ,按钮不再触发。

现在在某些情况下我可以让mat-button工作。 如果我在模板中调用locationsTest而不是使用getter,按钮将起作用。 如果我返回变量locationsTest ,getter 也可以工作。 此外,如果我从 getter 返回一个字符串数组或一个整数数组, mat-button将起作用,并且按钮将在单击时触发。 似乎只有 getter 返回一个硬编码的对象数组才会发生这种情况。

所以我的问题是有人知道为什么会发生这种情况吗? 下面是失败的用例,我不确定为什么会发生这种情况。 在下面进行测试时,请确保在安装 @angular/material 包后导入MatButtonModule ,否则mat-button什么也不做。

组件.html

<div *ngFor="let location of locations">
  <div>
    <h4>{{ location.name }}</h4>
    <p>{{ location.address }}</p>
    <p>{{ location.city }} </p>
  </div>
</div>

<button mat-button (click)="GoToLocation()">
  Go To Location
</button>

组件.ts

let locationsTest = [
    {
      name: "Walmart",
      address: "123 Mcdougal Street W",
      city: "Toronto"
    },
    {
     name: "Barber Shop",
     address: "22 cat Street",
     city: "Toronto"
   }
 ];

public get locations(): any {
  return [
    {
      name: "Walmart",
      address: "123 Mcdougal Street W",
      city: "Toronto"
    },
    {
     name: "Barber Shop",
     address: "22 cat Street",
     city: "Toronto"
   }
 ];
}

public GoToLocation(): void {
  console.log('Going to Location');
}

感谢您的任何见解。

此问题可能由多种不同的原因引起。 我建议尝试以下作为清单,因为这些总是最终成为我的原因:

  1. 是否安装了角材料?

    我发现有时我们会忘记安装 Angular 材料,并且由于尚未发现的其他错误而隐藏了错误。

  2. 模块是进口的吗? 在这种情况下 MatbuttonModule

    这是我遇到的另一个常见问题,我们忘记导入模块,因此 Angular 不知道组件或指令是什么。 在这种情况下,Angular 可能不知道mat-button指令是什么,但由于不同的错误,错误是无声的。

  3. (最常见)您使用了一个返回值的 getter,该值会自行更新!

    这是我在不起作用时发现的最常见的问题。 当我们开发返回模拟数据时,这是很常见的。 但是,如果您在 getter 中创建 Observable 或 BehaviorSubject 或设置一个值,您可能会导致 Angular 不断触发生命周期方法。 这反过来会阻止 Angular 功能触发,因为 Angular 正忙于不断更新。

    例子:

     //TS File: public get userNames(): Observable<Array<string>> { public names = new BehaviorSubject<Array<any>>(null); let mockNames = [ 'L1ghtk3ira', 'Thor4Life', 'OverwatchKing' ]; names.next(mockNames) return names.asObservable(); } /html file <ng-container *ngIf="userNames | async as listOfUserNames;'> <p *ngFor="let userName of listOfUserNames"> {{ userName }} </p> </ng-container>

    上面的这段代码看起来无害,但是当我们在模板中使用它时真正发生了什么。 当我们的*ngIf (或者即使我们直接在*ngFor循环中异步*ngFor )时,angular 获取数据并在此期间设置新数据。 Angular 会检测到这一点,并在当前更改检测完成后决定执行另一个更改检测。 当下一次更改检测发生时,此问题会重复发生。 因此,即使您在屏幕上看到没有变化,因为数据相同,它也会创建一个永无止境的变化检测循环。 因此,for 循环中的任何内容(click)例如(click)事件(click)永远不会被触发,因为 Angular 会不断检查和更新自身。

    有两种方法可以解决这个问题。 拳头很简单,我们以任何方式将值设置在 getter 之外,在我的示例中,我选择将其设置为初始值。 将过去的 TS 文件更改为以下内容:

     public names = new BehaviorSubject<Array<any>>( [ 'L1ghtk3ira', 'Thor4Life', 'OverwatchKing' ] ); public get userNames(): Observable<Array<string>> { return names.asObservable(); }

使用 Angular 记住的一个很好的经验法则是,如果您在模板中使用 getter,则永远不要在 getter 中设置值,因为它会触发无休止的变化检测。 虽然这在一般情况下应该不言而喻,尽管会发生错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM