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

我开始学习 Angular2。我一直在遵循 angular.io 提供的英雄教程。 一切运行良好,直到我对使用模板的 HTML 的混乱感到厌烦,我使用模板 URL 代替它,并将 HTML 移动到一个名为 hero.HTML 的文件中。 生成的错误是,“无法读取未定义的属性‘ name’”。 奇怪的是,可以访问指向对象数组的 heros 变量,这样 ngFor 将根据数组中对象的数量生成正确数量的“ li”标记。但是,无法访问数组对象的数据。 此外,即使是包含一些文本的简单变量,也不会在 HTML 中使用{{}}括号显示(参见提供的代码)。

应用程序组件

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' }
];

英雄

<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>

这是一张照片:

enter image description here

142803 次浏览

这条线

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

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

模板中的变量 selectedHeronull,因此不能按原样绑定 selectedHero.name。在这种情况下,你需要使用 猫王接线员 ?.:

<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 还不存在,因为用户还没有选择一个英雄,所以它返回未定义的。

<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 之外,直到它被选中,因此变为 true。

这个文档 帮助我理解了结构指令。

之所以会出现这个错误,是因为您遵循了“英雄”教程中写得很差的说明。我也遇到了同样的事。

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

若要在无序列表中显示英雄名称,请插入以下内容 下面的标题和上面的英雄详细信息的 HTML 块。

后面跟着这个代码块:

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

它没有指示您替换前面的详细代码,而且应该这样做。这就是为什么我们只剩下:

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

在我们的 *ngFor之外。

但是,如果你继续向下滚动页面,你会遇到以下情况:

展示英雄的模板应该是这样的:

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

请注意,以前的工作中没有细节元素。

作者这样的一个错误可能会导致一场徒劳的追逐。希望这篇文章能帮助其他人避免这种情况。

为了避免这种情况,您也可以将组件的 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 = '';
}
}

并确保您初始化了所选择的 Hero

selectedHero: Hero = new Hero();

在角度,有支持猫王操作员 ?.,以防止一个视图渲染失败。他们称之为 安全导航操作员安全导航操作员。以下面的例子为例:

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

由于它试图访问 null值的 name 属性,因此整个视图将消失,您可以在浏览器控制台中看到错误。它可以完美地处理诸如 a?.b?.c?.d这样的长属性路径。因此,我建议您每次需要访问模板中的属性时都使用它。