在构建模型/集合/类时我应该怎么想?

时间:2016-09-18 15:51:47

标签: angular ionic2

在整个周末,我一直在来回思考在为项目构建模型和类时我应该如何思考,而我却无法围绕它进行思考。

我会尝试尽可能地解释(如果我应该进一步解释请注释),我有一个远程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并得出结论,应该有办法做到这一点吗?

致以最诚挚的问候,

杰克蛇(不是摔跤手)

1 个答案:

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

更新:实施AsyncPipeHomeComponent现在归结为:

@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();
    }
}