首页 文章

如何在angular2中调用另一个组件函数

提问于
浏览
93

我有两个组件如下,我想从另一个组件调用一个函数 . 这两个组件都包含在第三个父组件using指令中 .

第1部分:

@component(
selector:'com1'
)
export class com1{
function1(){...}
}

第2部分:

@component(
selector:'com2'
)
export class com2{
function2(){...
// i want to call function 1 from com1 here
}
}

我已经尝试使用 @input@output ,但我不明白如何使用它以及如何调用该功能,任何人都可以帮忙吗?

6 回答

  • 17

    如果com1和com2是兄弟姐妹,你可以使用

    @component({
      selector:'com1',
    })
    export class com1{
      function1(){...}
    }
    

    com2使用 EventEmitter 发出事件

    @component({
      selector:'com2',
      template: `<button (click)="function2()">click</button>`
    )
    export class com2{
      @Output() myEvent = new EventEmitter();
      function2(){...
        this.myEvent.emit(null)
      }
    }
    

    这里父组件添加一个事件绑定来监听 myEvent 事件,然后在发生这样的事件时调用 com1.function1() . #com1 是一个模板变量,允许从模板中的其他位置引用此元素 . 我们使用它来 com2 com2myEvent 的事件处理程序:

    @component({
      selector:'parent',
      template: `<com1 #com1></com1><com2 (myEvent)="com1.function1()"></com2>`
    )
    export class com2{
    }
    

    有关组件之间通信的其他选项,另请参阅https://angular.io/docs/ts/latest/cookbook/component-communication.html

  • 25

    您可以从组件2访问组件的方法 .

    componentOne

    ngOnInit() {}
    
      public testCall(){
        alert("I am here..");    
      }
    

    componentTwo

    import { oneComponent } from '../one.component';
    
    
    @Component({
      providers:[oneComponent ],
      selector: 'app-two',
      templateUrl: ...
    }
    
    
    constructor(private comp: oneComponent ) { }
    
    public callMe(): void {
        this.comp.testCall();
      }
    

    componentTwo html文件

    <button (click)="callMe()">click</button>
    
  • 89

    它取决于组件(父/子)之间的关系,但制作通信组件的最佳/通用方法是使用共享服务 .

    有关详细信息,请参阅此文档:

    话虽这么说,您可以使用以下命令将com1的实例提供给com2:

    <div>
      <com1 #com1>...</com1>
      <com2 [com1ref]="com1">...</com2>
    </div>
    

    在com2中,您可以使用以下内容:

    @Component({
      selector:'com2'
    })
    export class com2{
      @Input()
      com1ref:com1;
    
      function2(){
        // i want to call function 1 from com1 here
        this.com1ref.function1();
      }
    }
    
  • 1

    第1部分(儿童):

    @Component(
      selector:'com1'
    )
    export class Component1{
      function1(){...}
    }
    

    组件2(父母):

    @Component(
      selector:'com2',
      template: `<com1 #component1></com1>`
    )
    export class Component2{
      @ViewChild("component1") component1: Component1;
    
      function2(){
        this.component1.function1();
      }
    }
    
  • 22

    我会尽力回答你的问题 .

    以前回答的所有人都是对的 . 首先,您需要了解组件之间的关系 . 然后你可以选择正确的沟通方式 . 我试着更多地解释你想要的小甜菜 . 并解释我所知道并在我的实践中用于组件之间通信的所有方法 .

    组件之间可以有哪些关系?

    1. Parent > Child

    enter image description here

    Sharing Data via Input

    这可能是共享数据的最常用方法 . 它的工作原理是使用 @Input() 装饰器来允许数据通过模板传递 .

    parent.component.ts

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'parent-component',
      template: `
        <child-component [childProperty]="parentProperty"></child-component>
      `,
      styleUrls: ['./parent.component.css']
    })
    export class ParentComponent{
      parentProperty = "I come from parent"
      constructor() { }
    }
    

    child.component.ts

    import { Component, Input } from '@angular/core';
    
    @Component({
      selector: 'child-component',
      template: `
          Hi {{ childProperty }}
      `,
      styleUrls: ['./child.component.css']
    })
    export class ChildComponent {
    
      @Input() childProperty: string;
    
      constructor() { }
    
    }
    

    这是一种非常简单的方法 . 它很容易使用 . 我们还可以使用ngOnChanges捕获子组件中数据的更改 .

    但是不要忘记,如果我们使用一个对象作为数据,并且在更改此对象的参数时,对它的引用不会改变 . 因此,如果我们想要在子组件中接收修改的对象,它必须是不可变的 .

    2. Child > Parent

    enter image description here

    Sharing Data via ViewChild

    ViewChild允许将一个组件注入另一个组件,使父组件可以访问其属性和功能 . 然而,有一点需要注意,在视图初始化之后,孩子将无法使用 . 这意味着我们需要实现AfterViewInit生命周期钩子来接收来自子节点的数据 .

    parent.component.ts

    import { Component, ViewChild, AfterViewInit } from '@angular/core';
    import { ChildComponent } from "../child/child.component";
    
    @Component({
      selector: 'parent-component',
      template: `
        Message: {{ message }}
        <child-compnent></child-compnent>
      `,
      styleUrls: ['./parent.component.css']
    })
    export class ParentComponent implements AfterViewInit {
    
      @ViewChild(ChildComponent) child;
    
      constructor() { }
    
      message:string;
    
      ngAfterViewInit() {
        this.message = this.child.message
      }
    }
    

    child.component.ts

    import { Component} from '@angular/core';
    
    @Component({
      selector: 'child-component',
      template: `
      `,
      styleUrls: ['./child.component.css']
    })
    export class ChildComponent {
    
      message = 'Hello!';
    
      constructor() { }
    
    }
    

    Sharing Data via Output() and EventEmitter

    共享数据的另一种方法是从子节点发出数据,父节点可以列出这些数据 . 当您希望共享按钮单击,表单条目和其他用户事件等内容发生的数据更改时,此方法非常理想 .

    parent.component.ts

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'parent-component',
      template: `
        Message: {{message}}
        <child-component (messageEvent)="receiveMessage($event)"></child-component>
      `,
      styleUrls: ['./parent.component.css']
    })
    export class ParentComponent {
    
      constructor() { }
    
      message:string;
    
      receiveMessage($event) {
        this.message = $event
      }
    }
    

    child.component.ts

    import { Component, Output, EventEmitter } from '@angular/core';
    
    @Component({
      selector: 'child-component',
      template: `
          <button (click)="sendMessage()">Send Message</button>
      `,
      styleUrls: ['./child.component.css']
    })
    export class ChildComponent {
    
      message: string = "Hello!"
    
      @Output() messageEvent = new EventEmitter<string>();
    
      constructor() { }
    
      sendMessage() {
        this.messageEvent.emit(this.message)
      }
    }
    

    3. Siblings

    enter image description here

    Child > Parent > Child

    我试着解释下面兄弟姐妹之间沟通的其他方式 . 但是你已经可以理解了解上述方法的方法之一 .

    parent.component.ts

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'parent-component',
      template: `
        Message: {{message}}
        <child-one-component (messageEvent)="receiveMessage($event)"></child1-component>
        <child-two-component [childMessage]="message"></child2-component>
      `,
      styleUrls: ['./parent.component.css']
    })
    export class ParentComponent {
    
      constructor() { }
    
      message:string;
    
      receiveMessage($event) {
        this.message = $event
      }
    }
    

    儿童one.component.ts

    import { Component, Output, EventEmitter } from '@angular/core';
    
    @Component({
      selector: 'child-one-component',
      template: `
          <button (click)="sendMessage()">Send Message</button>
      `,
      styleUrls: ['./child-one.component.css']
    })
    export class ChildOneComponent {
    
      message: string = "Hello!"
    
      @Output() messageEvent = new EventEmitter<string>();
    
      constructor() { }
    
      sendMessage() {
        this.messageEvent.emit(this.message)
      }
    }
    

    儿童two.component.ts

    import { Component, Input } from '@angular/core';
    
    @Component({
      selector: 'child-two-component',
      template: `
           {{ message }}
      `,
      styleUrls: ['./child-two.component.css']
    })
    export class ChildTwoComponent {
    
      @Input() childMessage: string;
    
      constructor() { }
    
    }
    

    4. Unrelated Components

    enter image description here

    我在下面描述的所有方法都可以用于组件之间关系的所有上述选项 . 但每个都有自己的优点和缺点 .

    Sharing Data with a Service

    在缺少直接连接的组件(如兄弟姐妹,孙子孙等)之间传递数据时,您应该使用共享服务 . 如果您的数据始终保持同步,我会发现RxJS BehaviorSubject在这种情况下非常有用 .

    data.service.ts

    import { Injectable } from '@angular/core';
    import { BehaviorSubject } from 'rxjs';
    
    @Injectable()
    export class DataService {
    
      private messageSource = new BehaviorSubject('default message');
      currentMessage = this.messageSource.asObservable();
    
      constructor() { }
    
      changeMessage(message: string) {
        this.messageSource.next(message)
      }
    
    }
    

    first.component.ts

    import { Component, OnInit } from '@angular/core';
    import { DataService } from "../data.service";
    
    @Component({
      selector: 'first-componennt',
      template: `
        {{message}}
      `,
      styleUrls: ['./first.component.css']
    })
    export class FirstComponent implements OnInit {
    
      message:string;
    
      constructor(private data: DataService) {
          // The approach in Angular 6 is to declare in constructor
          this.data.currentMessage.subscribe(message => this.message = message);
      }
    
      ngOnInit() {
        this.data.currentMessage.subscribe(message => this.message = message)
      }
    
    }
    

    second.component.ts

    import { Component, OnInit } from '@angular/core';
    import { DataService } from "../data.service";
    
    @Component({
      selector: 'second-component',
      template: `
        {{message}}
        <button (click)="newMessage()">New Message</button>
      `,
      styleUrls: ['./second.component.css']
    })
    export class SecondComponent implements OnInit {
    
      message:string;
    
      constructor(private data: DataService) { }
    
      ngOnInit() {
        this.data.currentMessage.subscribe(message => this.message = message)
      }
    
      newMessage() {
        this.data.changeMessage("Hello from Second Component")
      }
    
    }
    

    Sharing Data with a Route

    有时您不仅需要在组件之间传递简单数据,还需要保存页面的某些状态 . 例如,我们希望在在线市场中保存一些过滤器,然后复制此链接并发送给朋友 . 我们希望它以与我们相同的状态打开页面 . 第一种,也许是最快捷的方法是使用query parameters .

    查询参数看起来更像 /people?id= ,其中 id 可以等于任何东西,您可以拥有任意数量的参数 . 查询参数将由&符号分隔 .

    使用查询参数时,您无需在路径文件中定义它们,也可以将它们命名为参数 . 例如,请使用以下代码:

    page1.component.ts

    import {Component} from "@angular/core";
    import {Router, NavigationExtras} from "@angular/router";
    
    @Component({
        selector: "page1",
      template: `
        <button (click)="onTap()">Navigate to page2</button>
      `,
    })
    export class Page1Component {
    
        public constructor(private router: Router) { }
    
        public onTap() {
            let navigationExtras: NavigationExtras = {
                queryParams: {
                    "firstname": "Nic",
                    "lastname": "Raboy"
                }
            };
            this.router.navigate(["page2"], navigationExtras);
        }
    
    }
    

    在接收页面中,您将收到以下查询参数:

    page2.component.ts

    import {Component} from "@angular/core";
    import {ActivatedRoute} from "@angular/router";
    
    @Component({
        selector: "page2",
        template: `
             <span>{{firstname}}</span>
             <span>{{lastname}}</span>
          `,
    })
    export class Page2Component {
    
        firstname: string;
        lastname: string;
    
        public constructor(private route: ActivatedRoute) {
            this.route.queryParams.subscribe(params => {
                this.firstname = params["firstname"];
                this.lastname = params["lastname"];
            });
        }
    
    }
    

    NgRx

    迷失方式,更复杂但更强大是使用NGRX . 这个库不用于数据共享它是一个功能强大的状态管理库 . 我不能简单地解释如何使用它,但你可以去官方网站阅读有关它的文档 .

    对我来说,Ngrx商店解决了多个问题 . 例如,当您必须处理可观察对象以及在不同组件之间共享某些可观察数据的责任时 . 在这种情况下,存储操作和缩减器确保始终以“正确的方式”执行数据修改 .

    它还为HTTP请求缓存提供了可靠的解决方案 . 您将能够存储请求及其响应,以便您可以验证您正在进行的请求尚未存储响应 .

    你可以在那里阅读有关ngrx的内容并了解你是否需要在你的应用程序中使用它

    最后,我想说在选择一些共享数据的方法之前,您需要了解将来如何使用这些数据 . 我的意思是也许刚才你可以使用 @Input 装饰器来分享用户名和姓氏 . 然后,您将添加一个新组件或新模块(例如,管理面板),您还需要有关用户的信息 . 这意味着可能是将服务用于用户数据或其他方式共享数据的更好方式 . 在开始实现数据共享之前,您需要更多地考虑它 .

    我希望我的回答对很多人都有用 .

  • 51
    • 假设第一个组件是DbstatsMainComponent

    • 第二个组件DbstatsGraphComponent .

    • 第一个组件调用第二个方法

    <button (click)="dbgraph.displayTableGraph()">Graph</button> <dbstats-graph #dbgraph></dbstats-graph>

    请注意子组件上的局部变量 #dbgraph ,父组件可以使用它来访问其方法( dbgraph.displayTableGraph() ) .

相关问题