Ionic 2 / Angular 2 中的全局函数

9

如何设置一个全局函数,以便在所有视图中都可以访问?

在app.component.ts中,我添加了一个简单的方法。

  openShare() {console.log("button clicked")} 

然后在我的导航栏中,我有

  <button ion-button right (click)="openShare()">
  <ion-icon name="md-share"></ion-icon>
</button>

当我尝试从任何页面访问此内容时,会出现以下情况。
self.context.openShare is not a function

如果我直接将它放在构造函数中(例如 this.openShare()),它就能正常执行,但是当我使用 (click) 函数从任何页面调用它时,它就不起作用。

app.component.ts 不是全局的吗?我以为这就是我应该放置它的地方,但也许我错过了什么。

基本上,这是一个简单按钮所需的功能,但我需要它是全局的,因为它在每个页面上都被使用。

任何帮助都将不胜感激,还在摸索Ionic 2中。


尝试使用自定义指令。 - Harish Kommuri
有没有示例代码可以看一下?我要怎么做这个? - limit
https://angular.io/docs/ts/latest/guide/attribute-directives.html - Harish Kommuri
@HarishKommuri - 这也可能有效。如果有人有一个简单的例子,将不胜感激。我更喜欢视觉效果,不是要求编写代码,只需要一个关于点击方法的简单示例即可。 - limit
4个回答

11

你可以使用指令

按如下方式尝试:

将以下代码放入单独的指令文件中(social-sharing.directive.ts):

import { Directive, HostListener } from '@angular/core';

@Directive({
  selector: '[socialSharing]'
})
export class SocialSharing {

  constructor() { }

  @HostListener('click') onClick() {
    // Your click functionality
  }
}

将其导入到 app.module.ts 文件并添加到 declarations 中。

在 HTML 中,只需将attribute添加到任何元素中,该元素是指令文件中的selector

<button ion-button right socialSharing>
 <ion-icon name="md-share"></ion-icon>
</button>

附加信息:

从组件向指令传递值。

home.html

  <button ion-button right [socialSharing]="property">
    <ion-icon name="md-share"></ion-icon>
  </button>

home.component.ts

 export class HomePage {

   property: string = 'some url';
    constructor() {}
 }

social-sharing.directive.ts

@angular/core 导入 Input 以及其他内容。

import { Directive, Input, HostListener } from '@angular/core';

@Directive({
   selector: '[socialSharing]'
})

export class SocialSharing {
  @Input('socialSharing') str: string;

  constructor() {}

  @HostListener('click') onClick() {
     console.log(this.str);
  }
};

  ngAfterInit() {
     console.log(this.str);
  };
}

在指令中使用Element:

social-sharing.directive.ts

@angular/core中导入ElementRef以及其他内容。

 import { Directive, ElementRef, HostListener } from '@angular/core';

 @Directive({
   selector: '[socialSharing]'
 })

 export class SocialSharing {

   // Add ElementRef to constructor

   constructor(el: ElementRef) {};

   ngOnInit() {
      let elRef = this.el.nativeElement;
      console.log(elRef.innerHTML);        
   };
 }

嘿,谢谢。这真的完美地解决了问题。有很多人想知道如何做到这一点的帖子。希望他们能在这里找到你的答案。非常感谢你。 - limit

8
你可以使用提供者(Providers)轻松实现这一点。当你需要使用该功能(或提供者)时,只需将其注入(inject)到相关组件中即可。就是这样。 方法1: 你可以使用CLI来创建一个提供者。
> ionic g provider YourProvider

your-provider.ts

 import { Injectable } from '@angular/core';

    @Injectable()
    export class YourProvider {

      constructor() {
      }

       openShare() {console.log("button clicked")} 
    }

app.module.ts

import { YourProvider } from "../pages/path";

    @NgModule({
      declarations: [
        MyApp,
      ],
      imports: [
        IonicModule.forRoot(MyApp),
       ],
      bootstrap: [IonicApp],
      entryComponents: [
        MyApp,
        ],
      providers: [{ provide: ErrorHandler, useClass: IonicErrorHandler },YourProvider  ]
    })

    export class AppModule { }

your-view.ts

       import { YourProvider } from '../../providers/your-provider';

        export class YourViewPage{

          constructor(public yourProvider : YourProvider) {

          }

        openShare(){
           this.yourProvider.openShare(); 
        }

方法2:创建一个抽象基类。
my-base-class.ts
export abstract class MyBaseClass {

  constructor() {
  }

  protected openShare():void {
    console.log("button clicked"); 
  }

}

my-view.ts

export class MyViewPage extends MyBaseClass {
  constructor()
  {
     super();
  }

       openShare(){
               super.openShare(); 
            }
  }

嗯...是的,这就是我现在设置事物的方式,但对于一个简单的函数来说,在20页以上似乎导入了太多的内容。这是唯一的方法吗?这是用于导航头中的按钮,因此基本上在每个页面上都会调用。 - limit
谢谢帮忙。对抽象类很感兴趣,我会试一试的。 - limit
希望你能和我们分享结果 :) - Sampath

3

就像@Sampath提到的那样,一种方法是使用自定义提供程序。但是,由于您的方法只是一个简单的方法,我认为您可以使用Events代替。它应该是这样的:

在您的app.component.ts文件中,订阅新事件:

import { Events } from 'ionic-angular';

constructor(public events: Events, ...) {

  // ...

  events.subscribe('social:share', () => {

    // your code...
    console.log("button clicked");

  });

}

然后在任何其他页面上,只需发布事件即可执行该逻辑:

function anotherPageMethod() {
  this.events.publish('social:share');
}

2
谢谢,这可能有效。但是我仍然无法相信像导航栏这样全局的东西,没有一种简单的方法来声明公共方法。这样就不能保持DRY了。在Ionic 1中很简单。哎呀 - 非常感谢您的帮助。再次感谢。 - limit

0

对于任何看到这个的人,请考虑使用共享模块,该模块包含一个共享组件

通过以下方式使用Ionic CLI创建一个自定义组件,作为您的共享组件:

ionic g component components/nameofcomponent

其中nameofcomponent是您要为共享组件使用的名称

请参阅此文章以获取示例,了解如何创建一个共享模块来包含您的共享组件


你的回答可以通过提供更多支持性信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人能够确认你的回答是否正确。你可以在帮助中心找到关于如何撰写好回答的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接