【问题标题】:How to execute a function from another component that is NOT a sibling of the first component?如何从不是第一个组件的兄弟的另一个组件执行功能?
【发布时间】:2018-06-12 15:58:53
【问题描述】:

我正在尝试从另一个组件执行一个函数(这两个组件不是同级组件)。我的猜测是我需要使用 @Output 和 eventEmitter 来完成此操作或创建 Service 并订阅 Observable 以共享相同所有组件中的数据(我知道如何传递消息(字符串),但我不知道如何执行函数)。我不确定从哪里开始。我正在尝试从 function2 执行 function1。谁能帮我解决这个问题? 请提供一个 plunker。这是我的项目的样子:

   src
   |__app(FOLDER)
      |__home(FOLDER)
      |     |
      |     |__home.component.ts 
      |                  |______function2(){
      |                          What do I need to put in here to execute function1?
      |                          }
      | 
      |__products(FOLDER) 
           |
           |__tools(FOLDER)
                  |
                  |____tools.component.ts
                                   |____function1(){
                                         alert("I'm inside function 1!!");
                                         }

如您所见,我有一个具有 function2 的文件 home.component.ts 和一个具有 function1 的文件 tools.component.ts,所以任何想法如何执行函数 1 来自函数 2 ?

【问题讨论】:

  • 您是对的,您需要从函数 2 发出一个事件,该事件在 tools.component 中被监听,然后调用函数 1。您可以尝试的另一个选项是在组件之间共享服务它承载了一个可观察的。订阅 observable,然后从函数 2 更新,运行函数 1。
  • @Zze 你能分享你的想法作为解决方案吗?谢谢!
  • 对此进行测验,如果还不清楚,请告诉我。这不是您需要的 100%,但我将在此处的答案中使用类似的事件。 (我现在没有时间提出完整的答案)...stackoverflow.com/questions/38222475/…
  • 使用共享服务
  • 如果您的组件之间没有父子关系,则必须在高级模块上提供服务

标签: angular typescript angular-components


【解决方案1】:

我同意您关于可观察服务的想法是您最好的选择(正如其他人所建议的那样) - 尽管在这种情况下我更喜欢BehaviorSubject。这是一个简单的、有效的 plunkr,演示了如何实现它:

https://plnkr.co/edit/quHc2yOkxXIbXYUlnZbB?p=preview

如果我们分解需求,您需要的是一个事件代理服务,它只是传递事件。这个 plunkr 还可以通过服务传递一个参数对象——以防你需要这样做——但如果不是,那么只需传递你想要的任何对象(或者只是从所有方法中完全删除 param 参数)。

这个实现并不关心组件是不是兄弟 - 因为我们正在使用一个服务。无论您的应用程序结构如何,两者都将提供相同的服务实例。

为了快速参考,下面是一些重要的代码:

EventProxyService

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable()
export class EventProxyService {

 private eventSubject = new BehaviorSubject<any>(undefined);

 triggerSomeEvent(param: any) {
     this.eventSubject.next(param);
 }

 getEventSubject(): BehaviorSubject<any> {
    return this.eventSubject;
 }
}

第一组件

import { Component, OnInit } from '@angular/core';
import { EventProxyService } from './event-proxy.service';

@Component({
  selector: 'app-first',
  templateUrl: './src/first.component.html'
})
export class FirstComponent implements OnInit {
  displayText = 'I havent created any events yet.';
  constructor(private eventProxyService: EventProxyService) { }

  ngOnInit() { }

  triggerAnEvent() {
    this.eventProxyService.triggerSomeEvent(Date());
    this.displayText = 'I fired an event.'
  }
}

第二个组件

import { Component, OnInit } from '@angular/core';
import { EventProxyService } from './event-proxy.service';

@Component({
  selector: 'app-second',
  templateUrl: './src/second.component.html'
})
export class SecondComponent implements OnInit {

  displayText = 'I havent got an event yet';
  constructor(private eventProxyService: EventProxyService) { }

  ngOnInit() {
    this.eventProxyService.getEventSubject().subscribe((param: any) => {
      if (param !== undefined) {
        this.theTargetMethod(param);
      }
      });
  }

  theTargetMethod(param) {
    this.displayText = 'Target Method got called with parameter: "' + param + '"';
  }
}

【讨论】:

  • 非常感谢您的意见。我仍然需要对我的代码进行一些更新,但您的意见有所帮助!
  • @SteveLand ngOnDestroy() 上的取消订阅方法怎么样???为什么没用???
【解决方案2】:

使用服务。在 home.component 中订阅服务的 Observable 并在工具中执行 observable 的更改

//Your service
private dataSource = new Subject<any>();
data = this.searchDataSource.asObservable();
change(param:any) {
   this.searchDataSource.next(param)
}
//Your home.component
this.myService.data.subscribe((param: any) => {
      console.log(param)
}
//Your tool
this.myService.change("Hello world");

由于问题是执行一个函数,你可以使用这个想法,做一些类似

//Your tool:
    this.myService.change("Command1") 
//or even
    this.myService.change({"command":"Command1","arg":myvariable})

//Your home.component
this.myService.data.subscribe((param:any)=>
{  switch (param.command)
   {
      case "Command1":
          this.function1(param.arg);
          break;
      case "Command2":
          this.function2();
          break;
      ....
   }
}

【讨论】:

  • @HenryDev 我已经更新了我的答案。我知道这是一种解决方法,但这是我能想象的唯一方法
【解决方案3】:

根据您要执行的操作,您有两种选择。

首先:如果您需要 Angular 功能(例如依赖注入)或想要共享数据,您应该考虑使用服务。已经有足够多的文档和教程(请参阅angular docs。)我建议您仔细阅读。

第二:如果您只需要 JavaScript 功能,您可以创建一个 TypeScript 文件(例如 /src/app/shared/tools.ts 并将您的方法放在那里。这对于进行某种计算的静态函数非常有用,格式化或类似的。然后您可以在任何需要的地方导入和使用该函数。(提示:将其设为pure。)

【讨论】:

    【解决方案4】:

    继承组件。

    假设一个组件。

    @Component({
    ...
    })
    export class Component1 {
      constructor();
    
      public test1() {
        console.log("this is a test");
      }
    }
    

    您可以将inheritance 第一个组件作为子组件执行test1 方法

    @Component({
    ...
    })
    
    export Class Component2 extends Component1 {
      constructor();
    
      //Execute test1 method
      test1();
    }
    

    另外,请记住,如果您使用 Angular,则需要将组件导出到 declarationsentryComponents。您还需要将其导入新组件中。

    import { Component1 } from 'directory/component';
    

    /* 示例 */

    import { SplashScreen } from 'directory/splash-screen';

    【讨论】:

    • 希望对你有帮助!祝你好运!!
    • 所有解决方案都是导出类并从您的目录中导入它。
    • 这毫无意义。 OP 有不同的实例以单向方式通信:home [send event]->[receive] tools。他不需要分享行为(方法)
    • if there is no parent-child relation between your components, the service has to be provided on a high-level module。那是亲子关系。你自己说我在说什么
    • 当然,另一个解决方案通过服务共享功能。
    猜你喜欢
    • 2019-12-09
    • 2017-12-31
    • 2019-01-05
    • 1970-01-01
    • 2019-02-13
    • 2018-10-11
    • 2017-10-21
    • 2019-07-26
    • 1970-01-01
    相关资源
    最近更新 更多