Angular2:无法读取未定义的 属性 'name'

Angular2: Cannot read property 'name' of undefined

我开始学习Angular2了。我一直在关注 angular.io 上提供的英雄教程。 一切正常,直到我对使用模板的 HTML 的混乱感到恼火,我使用模板 URL 代替它,并将 HTML 移动到名为 hero.html 的文件. 生成的错误是 "Cannot read property 'name' of undefined"。 奇怪的是,可以访问指向对象数组的 heroes 变量,以便 ngFor 将根据数组中的对象数量生成正确数量的 "li" 标签。但是,无法访问数组对象的数据。 此外,即使是包含一些文本的简单变量,也不会在 HTML 中使用 {{}} 括号显示(参见提供的代码)。

app.component.ts

import { Component } from '@angular/core';
@Component({
  selector: 'my-app',
  templateUrl: './hero.html',
  styleUrls:['./styles.css']
})

export class AppComponent {
  title = 'Tour of Heroes';
  heroes = HEROES;
  selectedHero:Hero;

  onSelect(hero: Hero):void{
      this.selectedHero = hero;
  }
}

export class Hero{
   id: number;
   name: string;
}

const HEROES: Hero[] = [
   { id: 1, name: 'Mr. Nice' },
   { id: 2, name: 'Narco' },
   { id: 3, name: 'Bombasto' },
   { id: 4, name: 'Celeritas' },
   { id: 5, name: 'Magneta' },
   { id: 6, name: 'RubberMan' },
   { id: 7, name: 'Dynama' },
   { id: 8, name: 'Dr IQ' },
   { id: 9, name: 'Magma' },
   { id: 10, name: 'Tornado' }
];

hero.html

<h1>{{title}}</h1>
<h2>My Heroes</h2>
<ul class="heroes">
  <li *ngFor="let hero of heroes">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>
</ul>
<h2>{{hero.name}} details!</h2>
<div>
    <label>id: </label>{{hero.id}}
</div>
<div>
    <label>name: </label>
    <input [(ngModel)]="selectedHero.name" placeholder="name">
<div>

这是一张照片:

这一行

<h2>{{hero.name}} details!</h2>

*ngFor 之外并且没有 hero 因此 hero.name 失败。

变量 selectedHero 在模板中是 null,因此您不能按原样绑定 selectedHero.name。在这种情况下,您需要使用 elvis operator ?.

<input [ngModel]="selectedHero?.name" (ngModelChange)="selectedHero.name = $event" />

还需要将 [(ngModel)] 分离为 [ngModel](ngModelChange),因为您不能对使用 elvis 运算符的表达式进行赋值。

我也认为你的意思是使用:

<h2>{{selectedHero?.name}} details!</h2>

而不是:

<h2>{{hero.name}} details!</h2>

您只需要进一步阅读,您就会了解 *ngIf 结构指令。

selectedHero.name 尚不存在,因为用户尚未 select 英雄,因此 returns 未定义。

<div *ngIf="selectedHero">
  <h2>{{selectedHero.name}} details!</h2>
  <div><label>id: </label>{{selectedHero.id}}</div>
  <div>
    <label>name: </label>
    <input [(ngModel)]="selectedHero.name" placeholder="name"/>
  </div>
</div>

*ngIf 指令使 selectedHero 远离 DOM,直到它被 selected 并因此变为 truthy。

This document 帮助我理解了结构指令。

您收到此错误是因为您遵循了英雄教程中的 poorly-written 说明。我运行进入同样的事情。

具体来说,在在模板中显示英雄名称标题下,它指出:

To display the hero names in an unordered list, insert the following chunk of HTML below the title and above the hero details.

后跟此代码块:

<h2>My Heroes</h2>
<ul class="heroes">
  <li>
    <!-- each hero goes here -->
  </li>
</ul>

它没有指示您替换以前的详细代码,它应该。这就是我们剩下的原因:

<h2>{{hero.name}} details!</h2>

在我们的 *ngFor 之外。

但是,如果您进一步向下滚动页面,您将遇到以下情况:

The template for displaying heroes should look like this:

<h2>My Heroes</h2>
<ul class="heroes">
  <li *ngFor="let hero of heroes">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>
</ul>

请注意,之前的努力中缺少细节元素。

作者这样的错误可能会导致相当疯狂 goose-chase。希望这 post 可以帮助其他人避免这种情况。

为了避免这种情况,您也可以将组件的 selectedHero 成员初始化为空对象(而不是将其保留为未定义)。

在您的示例代码中,这将给出如下内容:

export class AppComponent {
  title = 'Tour of Heroes';
  heroes = HEROES;
  selectedHero:Hero = new Hero();

  onSelect(hero: Hero):void{
      this.selectedHero = hero;
  }
}

这对我有用:

export class Hero{
   id: number;
   name: string;

   public Hero(i: number, n: string){
     this.id = 0;
     this.name = '';
   }
 }

并确保你也初始化了 selectedHero

selectedHero: Hero = new Hero();

在 Angular 中,支持 elvis 运算符 ?. 以防止视图渲染失败。他们称之为 安全导航运算符 。举个例子:

The current person name is {{nullObject?.name}}

因为它试图访问 null 值的名称 属性,所以整个视图消失了,您可以在浏览器控制台中看到错误。它与长 属性 路径(例如 a?.b?.c?.d)完美配合。所以我建议您每次需要访问模板中的 属性 时都使用它。