最近我开始学习Angular,但是今天我遇到了一个问题。我有以下组件:
import { Component, OnInit } from '@angular/core';
import { SharedService } from '../home/shared.service';
import { IData } from '../data/IData';
@Component({
selector: 'app-current-article',
templateUrl: './current-article.component.html',
styleUrls: ['./current-article.component.css']
})
export class CurrentArticleComponent implements OnInit {
data: IData;
symbols: number = 150;
showReadMore = true;
contentToShow: string = "";
constructor(private _sharedService: SharedService) { }
ngOnInit() {
this.data = this._sharedService.sharedData;
this.contentToShow = this.data.content;
}
readMore() {
//this.symbols += 100;
}
}
“数据”属性是具有以下属性的对象:标题(字符串),authorId(数字)和内容(字符串)。
我还遵循this post的解决方案并提供了这项服务:
import { Injectable } from '@angular/core';
import { IData } from '../data/IData';
@Injectable()
export class SharedService{
sharedData: IData = {
title: "",
authorID: 0,
content: ""
};
insertData(data: IData){
this.sharedData.title = data.title;
this.sharedData.authorID = data.authorID;
this.sharedData.content = data.content;
}
}
我也有该组件的视图:
<div *ngIf="data.title">
<h1>{{ data.title }}</h1>
<h5>Author ID: {{ data.authorID }}</h5>
<div>
<span>{{ contentToShow }} </span>
<span>
<a href="#" *ngIf="showReadMore" (click)="readMore()">Read More ↪</a>
</span>
</div>
</div>
这是我的问题。 “ contentToShow”属性似乎未定义,我发现这很奇怪...但是,如果我尝试使用“ data.content”,它可以正常工作并显示我的数据。怎么了?我想解决2个小时,我开始认为它一定很明显,但是我不知道是什么...谢谢!
答案 0 :(得分:3)
在您将data.content
的值分配给contentToShow
时,该属性未设置,因此似乎未设置contentToShow
。您需要知道Javascript可与“按引用调用”一起使用,但仅适用于数组或对象,不适用于基本体(例如字符串,数字等)。
因此,在使用data.content
时您会看到一些价值。因为您直接从对象访问属性,并且更改的值显示在html中。
为更好地理解这篇文章,Is JavaScript a pass-by-reference or pass-by-value language?可以提供帮助。
解决问题的两种方法可以是:您可以使用data.content
,也可以通知组件值已更改,例如通过使用Observable。
最后一个看起来像这样:
@Injectable()
export class SharedService{
notfiySubject: Subject< IData > = new Subject();
...
insertData(data: IData){
this.sharedData.title = data.title;
this.sharedData.authorID = data.authorID;
this.sharedData.content = data.content;
// Emits the subject
this.notifySubject.next(this.sharedData);
}
}
在您的组件中,您将订阅该主题:
this._sharedService.notifySubject.subscribe(data => {
// Here you can set `contentToShow` with data or _sharedServices.sharedData
});
答案 1 :(得分:0)
问题在于您的“ contentToShow”是原始类型(字符串),并且已在ngOnInit中初始化(并且仅在此位置)。更新sharedData后,它会正确更新,但是contentToShow和this.data.content之间的连接会丢失。其实不在那里。
所以这永远都行不通:
<span>{{ contentToShow }} </span>
相反,您必须像这样从dataService保留对对象的引用:
<span>{{ data.content }} </span>
更新: 如果您仍想使用“ contentToShow”来自定义输出,那么您必须获得有关更改的通知。一种方法是在您的“ dataService”中添加一个Subject,如下所示:
dataChanged = new Subject<any>();
此主题到位后,您可以以此作为最后一行来更新“ insertData”方法:
this.sharedData.content = data.content;
this.dataChanged.next(); // <-- this will send the notification
}
在您的“ CurrentArticleComponent”(ngOnInit)中,您需要订阅此通知并像这样更新“ contentToShow”:
this._sharedService.dataChanged.subscribe(() => {
this.contentToShow = '??? ' + this.sharedService.sharedData.content + ' ???';
})
答案 2 :(得分:0)
基于此answer,它使用了类似的解决方案,但是OP的代码存在以下问题:
this.contentToShow = this.data.content;
不起作用,因为它不像上面的示例中那样引用对象data
。 this.contentToShow
是string
,每次数据被_sharedService
更改时,它都不知道这些更改,这与像这样{{1} }。现在this.data = this._sharedService.sharedData
和this.data
都指向同一个对象。
但是,如果我尝试使用“ data.content”,它就可以正常工作并显示我的数据。
之所以起作用,是因为组件使用对同一对象的引用并在发生更改时进行更新。
因此该解决方案在component.ts和模板中使用this._sharedService.sharedData
:
this.data
答案 3 :(得分:-1)
http
通话本质上是asyn
!
让我解释一下。最初,您将contentToShow
的值设置为""
,这是一个空字符串,并且适合角度,但是在ngOnInit()
调用中,您设置了this.contentToShow = this.data.content
可能未设置this._sharedService.sharedData
或正在等待服务器响应,而对于data: IData;
的初始值也可能未定义,因此this.data.content
将是undefined
在ngOnInit()
通话之后。
要解决此错误,只有以下代码可用this.contentToShow
时,您才能在init方法中设置the this.data.content
。
设置您的初始数据和内容:
data: IData = { content: '' };
,否则您可以在init调用中将其设置为''
。
ngOnInit() {
this.data = this._sharedService.sharedData;
this.contentToShow = this.data && this.data.content || '';
}