【问题标题】:How can I pass data back to my root page in Ionic 2?如何在 Ionic 2 中将数据传回我的根页面?
【发布时间】:2018-01-07 02:18:51
【问题描述】:

我有一个 Ionic 2 应用程序。该应用程序的前提是上课。一旦打开了一个类,用户就会被标记为在远程 API 中学习该类。

数据流向是:

  1. 用户打开“类”选项卡。
  2. 应用程序从 API 请求“类”数据。每个类都拥有该用户的“状态”。
  3. 用户选择一个类。这将使用NavController.push(Page, { 'classes': classObjFromApi }); 在应用中打开一个新视图。
  4. 堆栈中添加了几个页面,每个页面都传递了classes 对象。
  5. 在最后一页,API 被告知当前类已被占用,用户可以使用NavController.popToRoot() 导航回根目录

在根页面上会显示每个课程的状态(“未开始”、“进行中”、“已完成”)。在上述流程的第 5 点,用户被带回根目录,但这包含最初构造时的数据,显示类为“未启动”,即使它现在已“完成”。

如何从堆栈中的不同页面更新根页面上的数据?我曾假设popToRoot() 会接受navParams,所以我可以检查根页面中是否存在该数据,如果存在则使用它,如果不存在则从API 请求。

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

如果可以的话,我宁愿不使用内部存储,因为它会在加载页面时造成延迟,因为我必须等待从存储中提取数据才能显示它。

所以我的问题是:最好的方法是什么?如果是将数据传递给视图,如果popToRoot()不支持导航参数,我该怎么做?

【问题讨论】:

    标签: angular typescript ionic-framework ionic2 ionic3


    【解决方案1】:

    最好的方法是使用 Events

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

    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');
    }
    

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

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

    编辑

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

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

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

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

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

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

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

    【讨论】:

    • +1 推荐使用事件 - 虽然大量的监听器可能会减慢应用程序的速度,但这是一个非常有用的功能!
    • 太棒了,这正是我想要的。在此实例中,单个事件侦听器将节省大量 API 调用。
    • 很高兴听到这个消息!我已经编辑了答案以添加另一种方法来做到这一点,以防您需要对流程进行更多控制。但是与 Ionic Events 所做的非常相似,所以我想第一种方法在您的场景中已经绰绰有余了
    • 今天早上实施,效果很好。再次感谢。我已经使用事件重构了应用程序的其他一些部分,并且看到了一些性能优势。
    • 很高兴听到这个消息! :)
    猜你喜欢
    • 2017-06-29
    • 2017-07-19
    • 1970-01-01
    • 2017-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-04
    相关资源
    最近更新 更多