在整个周末,我一直在来回思考在为项目构建模型和类时我应该如何思考,而我却无法围绕它进行思考。
我会尝试尽可能地解释(如果我应该进一步解释请注释),我有一个远程api,我拿起一些将在应用程序中显示的列表。 API的响应是JSON,我将我的列表放在一个包含列表对象的简单数组结构中。
以下是我获取列表的RemoteService
提供商的一小段摘录:
export class RemoteService<Type> {
public resource: string;
private actionUrl: string;
private headers: Headers;
constructor(private _http: Http) {
this.actionUrl = 'API_URL';
this.headers = new Headers();
this.headers.append('Content-Type', 'application/json');
this.headers.append('Accept', 'application/json');
}
public GetAll = (): Observable<Type[]> => {
return this._http.get(this.actionUrl + this.resource)
.map((response: Response) => <Type[]>response.json())
.catch(this.handleError);
}
}
当我决定在我的主页上获取所有列表时,我将它们加载到页面控制器中的Observable Array
,然后我将映射结果并将每个对象实例化为ListModel
。< / p>
export class HomePage {
lists: Observable<Array<ListModel>>;
listsObserver: any;
constructor(public nav: NavController, public remoteService: RemoteService<ListModel>) {
this.lists = Observable.create(observer => {
this.listsObserver = observer;
});
this.remoteService.resource = 'lists';
this.remoteService
.GetAll()
.subscribe((data:ListModel[]) => {
this.listsObserver.next(data.map(list => new ListModel(list.lid, list.title, list.items)));
},
error => console.log(error),
() => console.log('Get all Items complete'));
}
}
ListModel
如下所示:
export class ListModel {
constructor(public lid: number, public title: string, public items: any[]) {
this.lid = lid;
this.items = items;
}
}
在完成所有这些之后,我开始怀疑自己是否这是一个很好的方法。我想了解如何正确使用角度2 ..
最后我的问题:
首先,我应该在ListModel
中创建观察者,而不是在我想要显示或获取列表的每个页面中创建观察者吗?或者我应该为此目的创建一个单独的ListCollection
,然后将其加载到我需要的地方?如果不是后者,那我该怎么想?
然后是另一个额外的问题,是否有可能将加载的对象从RemoteService
转换为动态模型,具体取决于我加载它的位置? I read the top comment here并得出结论,应该有办法做到这一点吗?
致以最诚挚的问候,
杰克蛇(不是摔跤手)
答案 0 :(得分:1)
从您发布的代码中,您通常似乎走在正确的轨道上!让我们看看一些细节。
RemoteService
目前,RemoteService
转换为该类型,但不会实例化该类型的真实对象。如果要实现通用解决方案,则应使用factory pattern(为简洁起见省略详细信息):
export interface TypeFactory<Type> {
public create(data:any):Type;
}
export class RemoteService<Type> {
constructor(private _http: Http, private factory:TypeFactory<Type>) {
// ...
}
public GetAll(): Observable<Type[]> => {
return this._http.get(this.actionUrl + this.resource)
.map((response: Response) => response.json())
.map((data:any) => {
// Now `data` should be an array of the expected type, depending on the server side.
// So we need to pass each element to the factory to create an actual instance.
// We will then return the array of instances to be emitted to the observable with the correct type.
return data.items.map((item:any) => this.factory.create(data));
})
.catch(this.handleError);
}
}
现在,GetAll()
observable确实会发出Type
个实例,因为工厂已经完成了它的工作。
TypeFactory
TypeFactory
的工作是将任意对象转换为具体的类实例。因此,让我们看看ListModel
:
export class ListModelFactory implements TypeFactory<ListModel> {
public create(data:any):ListModel {
// todo: validate data
return new ListModel(data.lid, data.title, data.items);
}
}
现在您可以连接这两个部分以达到您想要的效果(我假设您的HomePage
实际上是@Component
):
@Component(...)
export class HomePage implements OnInit {
lists: Array<ListModel>;
constructor(public nav: NavController, public remoteService: RemoteService<ListModel>) {
}
ngOnInit() {
this.remoteService
.GetAll()
.subscribe(
(data:ListModel[]) => this.lists = data,
error => console.log(error),
() => console.log('Get all Items complete')
);
}
}
在您的视图中,您现在可以访问lists
属性,以便在observable解析了值后输出您的数据。使用AsyncPipe,您可以进一步简化组件。
实际工厂隐藏在RemoteService<ListModel>
中,需要injected using DI。
更新:实施AsyncPipe。 HomeComponent
现在归结为:
@Component({
template: `<div *ngFor="let listModel of lists | async"> ... {{listModel}} ...</div>`
})
export class HomePage implements OnInit {
lists: Observable<Array<ListModel>>;
constructor(public nav: NavController, public remoteService: RemoteService<ListModel>) {
}
ngOnInit() {
this.lists = this.remoteService.GetAll();
}
}