构建 models/collections/classes 时我应该怎么想?
How should I think when building models/collections/classes?
整个周末,我一直在反复考虑在构建模型和 类 我的项目时应该如何思考,但我无法全神贯注。
我会尽力解释(如果我需要进一步解释请发表评论),我有一个遥控器 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
.
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;
}
}
做完所有这些之后,我开始怀疑自己这是否是个好方法。我想了解如何真正正确使用 angular 2..
最后是我的问题:
首先,我应该在 ListModel
中创建观察者,而不是在我想要显示或获取列表的每个页面中创建观察者吗?或者我应该为此创建一个单独的 ListCollection
然后在我需要的地方加载它吗?如果不是后者,那我该怎么想?
然后另一个额外的问题,是否可以根据我加载它的位置将加载的对象从 RemoteService
转换为动态模型? I read the top comment here 并得出结论,应该有办法做到这一点,对吗?
此致,
Jake the Snake(不是摔跤手)
从您发布的代码来看,您大体上似乎是在正确的轨道上!让我们看看一些细节。
在 RemoteService
中创建真实的 class 个实例
目前,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
的工作是将任意对象变成具体的 class 实例。那么让我们看看 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();
}
}
整个周末,我一直在反复考虑在构建模型和 类 我的项目时应该如何思考,但我无法全神贯注。
我会尽力解释(如果我需要进一步解释请发表评论),我有一个遥控器 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
.
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;
}
}
做完所有这些之后,我开始怀疑自己这是否是个好方法。我想了解如何真正正确使用 angular 2..
最后是我的问题:
首先,我应该在 ListModel
中创建观察者,而不是在我想要显示或获取列表的每个页面中创建观察者吗?或者我应该为此创建一个单独的 ListCollection
然后在我需要的地方加载它吗?如果不是后者,那我该怎么想?
然后另一个额外的问题,是否可以根据我加载它的位置将加载的对象从 RemoteService
转换为动态模型? I read the top comment here 并得出结论,应该有办法做到这一点,对吗?
此致,
Jake the Snake(不是摔跤手)
从您发布的代码来看,您大体上似乎是在正确的轨道上!让我们看看一些细节。
在 RemoteService
中创建真实的 class 个实例
目前,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
的工作是将任意对象变成具体的 class 实例。那么让我们看看 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();
}
}