typescript Angular在页面加载之前不初始化类属性

uqxowvwt  于 2023-05-08  发布在  TypeScript
关注(0)|答案(1)|浏览(137)

我对Angular还是个新手,在学习使用RxJS从AFS获取数据的教程时被卡住了
我成功地抓取了所需的,并将其记录到控制台中,但当相同的数据传递到一个类属性中以在我的组件视图中使用时,一切都中断了。我已经在这2个小时,我已经尝试实施解决类似的问题,我发现在这里SO,但都失败了。

model.ts

export interface Expenses {
  title: string,
  type: boolean,
  amount: number
}

*ExpenselistService.ts

import { Expenses } from '../models/expenses';

loadItems() {
  return this.afs.collection('expdata').snapshotChanges().pipe(
    map(dump => {
        return dump.map(a => {
          const id = a.payload.doc.id;
          const data = a.payload.doc.data();
          return {id, data};
        })
      })
    );
  }

component.ts

expenseData: Array<object>; //Always produce an error (not initialized by constructor and returns an empty array if muted or initialized manually)

  constructor(private exService: ExpenselistService) { }

  ngOnInit(): void {
    this.exService.loadItems('expdata').subscribe(values => {
    this.expenseData = values; // Successfully stores to property but still unavailable in component.html
    });
  }

component.html

<tr *ngFor="let exp of expenseData; let i = index">
  <td>{{ i }}</td>
  <td>{{ exp.data.title }}</td>
  <td>{{ exp.data.type }}</td>
  <td>{{ exp.data.amount | currency }}</td>
  <td class="dropdown">
    <button class="dropdown-toggle" data-toggle="dropdown">Action</button>
    <div class="dropdown-menu dropdown-menu-right">
      <a href="#" class="dropdown-item">Edit</a>
      <a href="#" class="dropdown-item">Delete</a>
    </div>
  </td>
</tr>

这个想法是显示所有数据将所有数据从service.ts通过component.ts传输到component. html,但component.ts总是向component. html返回一个未定义的对象,component. html会显示一个错误,说明'exp'没有'data'属性。
任何帮助将不胜感激,因为我没有线索似乎是什么问题

xxhby3vn

xxhby3vn1#

你的应用程序不工作,因为你没有在这里或在构造函数中初始化数组,如下所示:

expenseData: Array<object> = [];

另一种方法是删除subscription和数组初始化,这将有助于更好地维护您的应用程序,因为订阅不会自动取消订阅,这可能会导致内存泄漏。
让我们从重构expenseData变量开始,只是让它成为一个Observable(在最后添加$是一个约定,只是让我们/其他人知道这是一个可观察的),这简化了类型脚本,因为我们不再需要ngOnInit()

expenseData$ = this.exService.loadItems('expdata');

  constructor(private exService: ExpenselistService) { }

接下来在html中,我们只使用async管道,它将subscribe用于组件创建,unsubscribe用于组件销毁(修复潜在的内存泄漏)。然后,数据会像以前一样保存到exp变量中。

<tr *ngFor="let exp of expenseData$ | async; let i = index">
  <!-- The rest of the html -->
</tr>

在这些更改之后,我们将拥有一个更简单的组件,并且我们消除了由于忘记手动取消订阅而导致内存泄漏的可能性。
如果我们想更新进入异步管道的数据,我们需要做的就是重新分配并再次调用。这将自动取消订阅并重新订阅新的可观察对象,然后根据需要更新模板数据。

update() {
  this.expenseData = this.exService.loadItems('expdata');
}

相关问题