如何在Ionic 2中将数据传回我的根页?

问题描述:

我有一个Ionic 2应用程序。该应用程序的前提是上课。打开一个类后,用户被标记为在远程API中使用此类。

I have an Ionic 2 app. The premise of the app is to take a class. Once a class has been opened the user is marked as taking this class in the remote API.

数据流是:


  1. 用户打开类标签。

  2. 应用程序从API请求类数据。每个班级都拥有该用户的状态。

  3. 用户选择一个班级。这将在应用程序中使用 NavController.push(Page,{'classes':classObjFromApi})打开一个新视图;

  4. 那里是添加到堆栈的几个页面,每个页面都传递了对象。

  5. 在最后一页上,API被通知已经采用当前类,用户可以使用 NavController.popToRoot()

  1. User opens 'Classes' tab.
  2. App requests 'Classes' data from API. Each class holds a 'status' for that user.
  3. User selects a class. This opens a new view in the app using NavController.push(Page, { 'classes': classObjFromApi });.
  4. There are a few pages added to the stack, each has the classes object passed to it.
  5. On the final page the API is informed that the current class has been taken and the user can navigate back to the root using NavController.popToRoot()

$ b $导航回根目录b

在根页面上显示每个班级的状态('未开始','进行中','已完成')。在上面的流程中的第5点,用户被带回根,但是它具有最初构建时的数据,即使它现在已经完成,也将该类显示为未启动。

On the root page each class' status is shown ('Not started', 'In progress', 'completed'). At point 5 in the above flow the user is taken back to the root, but this has the data from when it was originally constructed, which shows the class as 'Not started', even though it's 'completed' now.

如何从堆栈中的其他页面更新根页面上的数据?我原以为 popToRoot()会接受 navParams 所以我可以检查根页中是否存在该数据如果存在则使用它,如果不存在则使用它。

How can I update the data on the root page from a different page in the stack? I had assumed that popToRoot() would accept navParams so I could check for the presence of that data in the root page and use it if it exists or request from the API if not.

我可以通过在上重新请求来自API的数据来解决这个问题。 ionViewDidEnter 方法,但这意味着每次用户查看此页面时都会发出API / HTTP请求,即使应用程序有数据也是如此。看起来很乱。

I can get around this by re-requesting data from the API on the ionViewDidEnter method, but that means an API/HTTP request every time the user views this page, even though the app has the data. Seems messy.

如果我可以提供帮助,我宁愿不使用内部存储,因为它在加载页面时会产生延迟,因为我必须等待数据到在显示之前从存储中取出。

I'd rather not use internal storage if I can help it, as it creates a delay when loading the page, as I have to wait for data to be pulled from storage before displaying it.

所以我的问题:这样做的最佳方法是什么?如果要将数据传递给视图,如果 popToRoot()不支持nav params,我该怎么做?

So my question: what's the best way of doing this? If it is to pass data to the view, how do I do that if popToRoot() doesn't support nav params?

最好的方法是使用 事件

The best way to do that would be by using Events:

在您的根页面中,订阅自定义事件,每次事件发生时执行一些代码已公布:

In your root page, subscribe to a custom event, to execute some code every time that event is published:

import { Events } from 'ionic-angular';

constructor(public events: Events) {
  events.subscribe('status:updated', (updatedData) => {
    // You can use the updatedData to update the view
    // ...
  });
}

// Clean up the subscription when the page is about to be destroyed
ionViewWillUnload() {
  this.events.unsubscribe('status:updated');
}

当用户更改该数据时,在任何其他页面中发布该事件:

And publish that event in any other page, when the user changes that data:

import { Events } from 'ionic-angular';

constructor(public events: Events) {}

yourMethod(): void {
  // Your custom logic...
  // ...

  // Now you can publish the event to update the root page (and any other page subscribed to this event)
  this.events.publish('status:updated', updatedData);
}






编辑

另一种方法是使用共享服务,并使用主题来发布/订阅更改。结果与 Ionic Event的非常相似,但在这种情况下,您需要添加共享服务,然后在更新数据时使用它。我更喜欢Ionic Events,但为了以防万一,你可以这样做:

Another way to do that, would be by using a shared service, and using a Subject to publish/subscribe to changes. The result would be pretty similar to Ionic Event's, but in this scenario you'd need to add a shared service and then use it when the data is updated. I'd prefer Ionic Events, but just in case, this is how you could do it:

import { Subject } from 'rxjs/Subject';

@Injectable()
export class MySharedService {
  public onDataChange: Subject<any>;

  constructor() {
    this.onDataChange = new Subject<any>();
  }

  public publishUpdate(newData): void {
    // Send the data to all the subscribers
    this.onDataChange.next(newData);
  } 
}

现在在您的根页面中订阅更改使用共享服务

So now in your root page, subscribe to the changes using the shared service

import { Subscription } from 'rxjs/Subscription';

// ...

private onDataChangeSubscription: Subscription;

constructor(public mySharedService: MySharedService) {
  this.onDataChangeSubscription = mySharedService.onDataChange.subscribe(
    updatedData => {
      // You can use the updatedData to update the view
      // ...
    });
}

// Clean up the subscription when the page is about to be destroyed
ionViewWillUnload() {
  this.onDataChangeSubscription.unsubscribe();
}

在更新数据时你也需要使用共享服务任何其他页面:

And you'd need to use the shared service too when updating the data from any other page:

constructor(public mySharedService: MySharedService) {}

yourMethod(): void {
  // Your custom logic...
  // ...

  // Now you can publish the event to update the root page (and any other page subscribed to this event)
  this.mySharedService.publishUpdate(updatedData);
}

如果每次需要执行一些自定义逻辑,这种方法可能会更好数据已更新,因此您可以在共享服务中执行此操作,而不是在每个订阅服务器上执行此操作,并广播结果...

This approach may be better if you need to execute some custom logic every time the data is updated, so instead of doing that on each subscriber, you could just do it in the shared service, and broadcast the result...