【问题标题】:ionic 2 page change eventionic 2 页面更改事件
【发布时间】:2017-02-11 15:47:39
【问题描述】:

我想在每次页面更改时执行一些代码。

我可以为每个页面添加一个ngOnDestroy 方法。看来我可以使用 Ionic 2 页面 lifecycle hooks(例如 ionViewDidUnload)获得完全相同的效果,但我没有费心去测试它。我宁愿在主应用程序类中添加一个方法。

我看到你可以订阅 Angular 2 Router events。我如何翻译它以在 Ionic 2 中使用?我首先收到import { Router } from '@angular/router; 的错误:

TypeScript error: <path>/node_modules/@angular/router/src/common_router_providers.d.ts(9,55): Error TS2305: Module '"<path>/node_modules/@angular/core/index"' has no exported member 'NgModuleFactoryLoader'.
TypeScript error: <path>/node_modules/@angular/router/src/router.d.ts(14,39): Error TS2305: Module '"<path>/node_modules/@angular/core/index"' has no exported member 'NgModuleFactoryLoader'.
TypeScript error: <path>/node_modules/@angular/router/src/router_module.d.ts(9,10): Error TS2305: Module '"<path>/node_modules/@angular/core/index"' has no exported member 'ModuleWithProviders'.

webpack 配置

var path = require('path');


module.exports = {
  entry: [
    path.normalize('es6-shim/es6-shim.min'),
    'reflect-metadata',
    path.normalize('zone.js/dist/zone'),
    path.resolve('app/app.ts')
  ],
  output: {
    path: path.resolve('www/build/js'),
    filename: 'app.bundle.js',
    pathinfo: false // show module paths in the bundle, handy for debugging
  },
  module: {
    loaders: [
      {
        test: /\.ts$/,
        loader: 'awesome-typescript',
        query: {
          doTypeCheck: true,
          resolveGlobs: false,
          externals: ['typings/browser.d.ts']
        },
        include: path.resolve('app'),
        exclude: /node_modules/
      }
    ],
    noParse: [
      /es6-shim/,
      /reflect-metadata/,
      /zone\.js(\/|\\)dist(\/|\\)zone/
    ]
  },
  resolve: {
    alias: {
      'angular2': path.resolve('node_modules/angular2')
    },
    extensions: ["", ".js", ".ts"]
  }
};

无论如何,如果有办法使用 ionic-angular 的 NavNavController 服务,那对我来说会更有意义。有没有办法做到这一点?

【问题讨论】:

    标签: angular typescript ionic-framework ionic2 ionic3


    【解决方案1】:

    Ionic2 不使用Angular2's Router。他们有自己的实现NavController


    我看到您可以订阅 Angular 2 路由器事件。我如何能 翻译它以在 Ionic 2 中使用?

    您可以合并所有NavController Events并订阅它。

    allEvents = Observable.merge(
                     this.navController.viewDidLoad, 
                     this.navController.viewWillEnter, 
                     this.navController.viewDidEnter, 
                     this.navController.viewWillLeave, 
                     this.navController.viewDidLeave, 
                     this.navController.viewWillUnload);
    
    allEvents.subscribe((e) => {
        console.log(e);
    });
    

    【讨论】:

    • 我应该把这段代码放在哪里?我尝试将其添加到 app.ts 构造函数中,但没有成功。
    • 你只能在声明至少一个NavController实例后才能使用它,它和Angulr的路由器有点不同
    • 我将它添加到我的主页/欢迎页面构造函数中,它似乎有效。谢谢。我想把代码放在不那么晦涩的地方(app.ts)。有没有办法做到这一点?当我尝试在应用程序构造函数中注入 NavController 时,它显示“没有 NavController 的提供者。”
    • 谢谢,viewWillUnload 到目前为止为我工作。我仍然有兴趣在 app/app.ts 中找到它,而不是在 pages/home/home.ts 中隐晦地找到它。
    【解决方案2】:

    另一种选择是创建一个超类,您可以在其中使用ionViewDidUnload 方法(或任何其他生命周期挂钩),如下所示:

    import { Events } from 'ionic-angular';
    
    export class BasePage {
    
      constructor(public eventsCtrl: Events) { }
    
      ionViewDidEnter() {
        this.eventsCtrl.publish('page:load');   
      }
    
      ionViewDidUnload() {
        this.eventsCtrl.publish('page:unload');   
      }
    }
    

    然后在每一页你只需要extend那个BasePage

    @Component({
      templateUrl: 'build/pages/my-page/my-page.html',
    })
    export class MyPage extends BasePage {
    
    constructor(private platform: Platform,
                  private nav: NavController, 
                  private menuCtrl: MenuController,
                  ...,
                  eventsCtrl: Events) //notice that this one does not have the private/public keyword 
      {    
    
        // Due to an issue in angular, by now you must send the dependency to the super class
        // https://github.com/angular/angular/issues/5155
        super(eventsCtrl);
    
        //...
    }
    

    然后,您可以在 app.ts 主文件中添加类似这样的方法来响应这些事件:

      private initializeEventHandlers() {
    
        this.events.subscribe('page:load', () => {
          // your code...
        });
    
        this.events.subscribe('page:unload', () => {
          // your code...
        });
    
      }
    

    【讨论】:

    • 我比较喜欢这个选项。另一方面,如果我要面对离子和棱角分明的恐怖,我为什么要使用香草打字稿来做这样的事情?
    【解决方案3】:

    从 Ionic 3.6 开始,您可以使用 App 组件来订阅应用程序范围的页面更改事件,如以下文档所述:https://ionicframework.com/docs/api/components/app/App/

    例如,如果您想使用 GA cordova 插件跟踪 Google Analytics(分析)中的每个视图更改,您可以像这样修改您的 app.component.ts:

    constructor(private app: App, private platform: Platform, private ga: GoogleAnalytics, ...) {
      this.platform.ready().then(() => {
        this.ga.startTrackerWithId('UA-XXX').then(() => {
          this.app.viewDidEnter.subscribe((evt) => {
            // evt.instance is the Ionic page component
            this.ga.trackView(evt.instance.title);
          });
        }).catch(e => console.log('Doh', e));
      }
    }
    

    【讨论】:

      【解决方案4】:

      第一件事路由器存在于@angular/router 模块中。

      对于监听路由更改事件,您可以在路由器changes 对象上订阅。

      代码

      class MyRouteEventClass {
        constructor(private router: Router) {
           router.changes.subscribe((val) => {
             /* Awesome code here */
           }
          )
        }
      }
      

      【讨论】:

      • 是的,对不起,这是一个错字。我添加了我遇到的错误。
      • 请加systemjs.config.js(模块加载器配置)
      • 我似乎没有任何同名的文件。
      • 啊,我认为是webpack。我将 webpack.config.js 添加到问题中。
      • 嗯,这似乎是一个不错的选择,但如果我不能在 ionic 中导入路由器,那对我来说就没有好处了。
      【解决方案5】:

      您可以使用普通的旧 Javascript 将其放置在 app.component.ts 中。假设您使用 Ionic2-RC0:

      import { Component } from '@angular/core';
      import { Platform } from 'ionic-angular';
      import { StatusBar } from 'ionic-native';
      
      import { YourPage } from '../pages/yourpage/yourpage';
      
      @Component({
        template: `<ion-nav [root]="rootPage"></ion-nav>`
      })
      export class MyApp {
        rootPage = YourPage;
      
        constructor(platform: Platform) {
          platform.ready().then(() => {
      
            // Okay, so the platform is ready and our plugins are available.
            // Here you can do any higher level native things you might need.
            StatusBar.styleDefault();
            window.addEventListener('load', () =>{
               console.log('page changed');
            });
          });
        }
      

      每次使用 NavController 更改页面时,都会在控制台中打印出page changed

      【讨论】:

      • 我喜欢这个答案,但看起来 load 事件只在开始时触发一次,而不是每次页面更改时触发。
      • 您可以使用focusout 代替load。它适用于每个新页面加载。但是,它不适用于 NavController.pop。
      • 太棒了。无论如何,我实际上现在关心 离开 页面,所以这似乎是正确的。是否还有其他时候我需要担心focusout 事件会触发?
      • 如果你把它应用到window,不,我不这么认为。我用 Nav poppushsetRoot 做了一些尝试。可能在打开打开外部应用的时候,比如你使用SocialSharing Cordova插件,在弹出原生分享菜单的时候应该触发focusout
      • 嗯,我没有挖太多,但它似乎确实在其他时间开火。我只是希望它在离开页面时停止播放所有音频和免费音频资源,但是当我点击播放按钮时会触发 focusout!所以所有的音频在播放之前都会被释放。
      【解决方案6】:

      在 Ionic2+ 中,您可以简单地订阅要执行代码的事件,如下所示:

      this.navCtrl.ionViewWillUnload.subscribe(view => {
          console.log(view);
      });
      

      您可以订阅所有Lifecycle Events

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-19
        • 2017-09-21
        • 1970-01-01
        • 1970-01-01
        • 2017-06-29
        • 2018-10-24
        • 1970-01-01
        • 2016-09-11
        相关资源
        最近更新 更多