【问题标题】:Component rendered before calling constructor or ngOnInit在调用构造函数或 ngOnInit 之前渲染的组件
【发布时间】:2019-03-11 04:30:53
【问题描述】:

我是 Angular 7 的初学者。

当我在调试中使用 getKeys()、构造函数和 ngOnInit 中的断点启动应用程序时,我可以看到首先调用了 getKeys()。在我看来,组件是在调用构造函数或 ngOnInit 之前呈现的。 为什么会这样,我该怎么办? 这对我来说是个问题,因为在 ngOnInit 中我初始化了我在 getKeys 中使用的 Map。

我的 task-list.component.html 的摘录

<div class="task-group" *ngFor="let key of getKeys()">
  <h1><span class="key badge badge-secondary">{{ key.displayValue }}&nbsp;
      <span class="badge badge-light">{{ getTasksByKey(key).length }}</span></span></h1>


  <task *ngFor="let task of getTasksByKey(key)" [task]="task"></task>
</div>

我的 task-list.component.ts 的摘录

...


@Component({
  selector: 'task-list',
  templateUrl: './task-list.component.html',
  styleUrls: ['./task-list.component.scss']
})
export class TaskListComponent implements OnInit {

  @Input() tasks: Task[];

  private mapExtractorByView: Map<TaskListViewEnum, KeyExtractor<Task>>;
  private _viewMode: TaskListViewEnum;


  constructor() {
    this.viewMode = TaskListViewEnum.byDate;
  }

  ngOnInit() {
    this.mapExtractorByView = new Map<TaskListViewEnum, KeyExtractor<Task>>();
    this.mapExtractorByView.set(TaskListViewEnum.byDate, (t: Task) => new Key(t.date, formatDate(t.date, "fullDate", "fr")));
    this.mapExtractorByView.set(TaskListViewEnum.byTag, (t: Task) => new Key(t.tags, t.tags));
  }

  getKeys() {
    return CollectionUtils.extractKeys(this.tasks, this.mapExtractorByView.get(this._viewMode));
  }

  getTasksByKey(key: Key) {
    return CollectionUtils.getElementsByKey(this.tasks, this.mapExtractorByView.get(this._viewMode), key);
  }

  @Input()
  set viewMode(viewMode: TaskListViewEnum) {
    this._viewMode = viewMode;
  }
}

【问题讨论】:

  • 尝试console.log(this);在每个方法(getKeys、构造函数和 ngOnInit)中并比较它们,您是否每次都看到相同的对象?您也可以创建一个临时属性并使用随机数初始化它,例如:dummy = Math.random();

标签: angular


【解决方案1】:

您是否可能忘记提供父组件的任务? 如果你初始化你的任务,比如@Input() tasks: Task[] = [];

模板应该成功渲染和工作,但模板仍将在ngOnInit 之前评估,如Angular 2: A property set during OnInit is undefined on the template 中所述

另一种选择是使用OnChanges 接口。 我创建了一个 stackblitz 来展示它是如何工作的 -> https://stackblitz.com/edit/angular-qoexkz?file=src%2Fapp%2Fapp.component.ts

请注意,我包含了两个示例,第一个循环使用OnChanges,第二个就是您使用的方法。 您会注意到,如果您推送任务,OnChanges 示例将不会更新,因为 OnChanges 只会在 @Input tasks 的引用发生变化时触发(这就是 Angular 的工作原理)。 这可以通过单击change Tasks 按钮来观察。

根据您的需要,OnChanges 可能适合您。

【讨论】:

    猜你喜欢
    • 2018-09-19
    • 1970-01-01
    • 2019-06-10
    • 2017-06-23
    • 2018-05-05
    • 2022-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多