【问题标题】:Angular 2 component DOM binds to the property in component before it has bean resolved in OnInit methodAngular 2 组件 DOM 在 OnInit 方法中解析 bean 之前绑定到组件中的属性
【发布时间】:2017-01-13 18:52:52
【问题描述】:

我正在学习 Angular 2 并尝试按照他们的教程进行操作。 这是返回模拟对象文件夹的“承诺”的服务的代码。

import {Injectable, OnInit} from "@angular/core";
import {FOLDER} from "./mock-folder";
import {Folder} from "./folder";
@Injectable()
export class FolderService {
  getFolder():Promise<Folder>{
    return Promise.resolve(FOLDER);
  }
}

它在我的 FolderModule 的提供者中声明

import {NgModule} from "@angular/core";
import {CommonModule} from "@angular/common";
import {FolderComponent} from "./folder.component";
import {MaterialModule} from "@angular/material";
import {FolderService} from "./folder.service";
@NgModule({
  imports:[CommonModule, MaterialModule.forRoot()],
  exports:[FolderComponent],
  declarations:[FolderComponent],
  providers:[FolderService]
})
export class FolderModule{

}

文件夹组件应该导入FolderService并使用它来获取文件夹对象。

import {Component, OnInit} from "@angular/core";
import {Folder} from "./folder";
import {FolderService} from "./folder.service";
@Component({
  selector: 'folder',
  moduleId: module.id,
  templateUrl: "./folder.component.html"
})
export class FolderComponent implements OnInit {
  folder:Folder;

  constructor(private folderService:FolderService) {
  }
  ngOnInit():void {
    this.getFolder();
  }
  getFolder() {
    this.folderService.getFolder().then((folder) => this.folder = folder);
  }
}

是的,我确实在根模块中导入了我的 FolderModule

@NgModule({
  imports: [BrowserModule, CommonModule, MaterialModule.forRoot(), FolderModule, AppRoutingModule],
  providers:[],
  declarations: [AppComponent, LifeMapComponent, MyPageNotFoundComponent],
  bootstrap: [AppComponent]
})
export class AppModule {
}

这里是文件夹组件模板

<md-grid-list cols="3" [style.background] ="'lightblue'" gutterSize="5px">
  <md-grid-tile *ngFor="let card of folder.cards">{{card.title}}</md-grid-tile>
</md-grid-list>

这是我在控制台中遇到的错误

异常:未捕获(承诺中):错误:错误 http://localhost:3000/app/folders/folder.component.html:1:16引起 作者:无法读取未定义类型错误的属性“卡片”:无法读取 未定义的属性“卡片”

export class Folder {
  public id:number;
  public title:string;
  public cards:Card[];
}

export class Card{
  id :number;
  title:string;
}

【问题讨论】:

    标签: javascript angular


    【解决方案1】:

    沃兰德,

    这可以通过在被迭代的集合上使用“Elvis”运算符来解决。

    <md-grid-tile *ngFor="let card of folder.cards">{{card.title}}</md-grid-tile>
    

    应该是:

    <md-grid-tile *ngFor="let card of folder?.cards">{{card?.title}}</md-grid-tile>
    

    注意“?”文件夹之后 - 这将强制整个路径为“null”,因此它不会迭代。问题在于空对象上的访问器。

    您还可以将文件夹声明为空数组 [] 以防止这种情况发生。

    编辑:对于任何旁观者,请注意 Elvis 运算符在您的 Typescript 代码中不可用,因为该语言不支持它。我相信 Angular 2 支持它,因此它可以在您的视图中使用(对于 AJAX 请求非常有用,您的数据尚未到达组件实例化点!)

    【讨论】:

      【解决方案2】:

      使用*ngIf 指令:

      <md-grid-list *ngIf="folder" cols="3" [style.background] ="'lightblue'" gutterSize="5px">
        <md-grid-tile *ngFor="let card of folder.cards">{{card.title}}</md-grid-tile>
      </md-grid-list>
      

      Angular 会在 promise 解决之前尝试渲染 html,因此 folderundefined 并抛出异常。
      使用*ngIf="folder",你告诉 Angular 如果表达式是假的,它应该忽略子元素。

      如果folder 不是undefined,则&lt;md-grid-tile *ngFor="let card of folder.cards"&gt;{{card.title}}&lt;/md-grid-tile&gt; 将被添加到DOM。

      【讨论】:

      • 是的,谢谢,我知道,它可以像这样解决,但是有没有更优雅的解决方案,在教程中它似乎在没有“if”语句的情况下工作。
      • 我觉得没有更“优雅”的解决方案了,看看official docs
      【解决方案3】:

      你的错误在类中:

      export class Folder {
        public id:number;
        public title:string;
        public cards:Card[];
      }
      
      export class Card{
        id :number;
        title:string;
      }
      

      你忘记了构造函数:

      export class Folder {
        constructor( 
           public id:number,
           public title:string,
           public cards:Card[])
        {}
      }
      
      export class Card{
        constructor( 
          public id :number,
          public title:string)
        { }
      }
      

      并且可能如之前建议的那样使用 elvis 运算符或 ngIf。

      【讨论】:

      • 不,文件夹是一个对象,但它有一个属性“cards”,它是数组,我想遍历这个数组而不是文件夹属性。
      • 好的,我想我应该坚持使用 Elvis 运算符,谢谢 :)
      猜你喜欢
      • 2016-07-21
      • 2016-12-11
      • 2018-02-13
      • 2016-07-15
      • 2018-03-26
      • 1970-01-01
      • 1970-01-01
      • 2016-03-27
      • 2020-11-17
      相关资源
      最近更新 更多