如何在另一个组件中获取指令/组件实例?

Posted

技术标签:

【中文标题】如何在另一个组件中获取指令/组件实例?【英文标题】:How can I get a directive/component instance inside another component? 【发布时间】:2016-09-05 08:33:28 【问题描述】:

我有一个 AlertComponent,我想将它用作我的 AppComponent 中的指令并将其公开,以便它可用于(作为一种单例)来自 AppComponent 的所有路由/子组件。但我似乎无法找到一种方法来获取用作指令的 AlertComponent 对象的实例,以便调用它的方法并查看对指令所做的更改(即在页面中添加/删除警报)。

这里是警报组件:

import  Component  from 'angular2/core';

import  Alert  from './model';

@Component(
    selector: 'alerts',
    templateUrl: './alert/index.html'
)
export class AlertComponent 
    alerts: Array<Alert>;

    constructor() 

    add(alert: Alert) 
        this.alerts.push(alert);
    

    remove(index: number) 
        this.alerts.splice(index, 1);
    

    clear() 
        this.alerts = [];
    


export  Alert ;

和 AppComponent:

import  Component, OnInit, provide  from 'angular2/core';
import  RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS  from 'angular2/router';
import  HTTP_PROVIDERS, RequestOptions  from 'angular2/http';
import  CookieService  from 'angular2-cookie/core';

import  UserComponent  from '../user/component';
import  AlertComponent, Alert  from '../alert/component';

import  ExtendedRequestOptions  from '../extended/RequestOptions';
import  UtilObservable  from '../util/observable';

@Component(
    selector: 'app',
    template: `
<alerts></alerts>
<router-outlet></router-outlet>
`,
    //styleUrls: [ 'app/style.css' ],
    directives: [
        ROUTER_DIRECTIVES,
        AlertComponent
    ],
    providers: [
        ROUTER_PROVIDERS,
        HTTP_PROVIDERS,
        provide(RequestOptions,  useClass: ExtendedRequestOptions ),
        CookieService,
        UtilObservable,
        AlertComponent
    ]
)
@RouteConfig([
    path: '/user/:action',
    name: 'User',
    component: UserComponent,
    useAsDefault: true

])
export class AppComponent implements OnInit 

    constructor(public _alert: AlertComponent) 

    ngOnInit() 
        this._alert.add(new Alert('success', 'Success!'));
    

我希望 AppComponent 的所有后代路由/子级(例如 UserComponent)都可以使用相同的 AlertComponent 实例,以便将警报添加到同一指令。

这可能吗?还是有其他更合适的方法来做到这一点?

[更新]

选择的解决方案回答了标题问题,但我也希望有一个简单的解决方案来在我的组件之间共享警报。这样做的方法如下:

警报组件:

import  Component  from 'angular2/core';

import  Alert  from './model';

export class Alerts extends Array<Alert> 

@Component(
    selector: 'alerts',
    templateUrl: './alert/index.html'
)
export class AlertComponent 
    constructor(public alerts: Alerts) 

    add(alert: Alert) 
        this.alerts.push(alert);
    

    remove(index: number) 
        this.alerts.splice(index, 1);
    

    clear() 
        this.alerts.length = 0;
    


export  Alert ;

应用组件:

import  Component, provide  from 'angular2/core';
import  RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS  from 'angular2/router';
import  HTTP_PROVIDERS, RequestOptions  from 'angular2/http';

import  AlertComponent, Alerts  from '../alert/component'
import  UserComponent  from '../user/component';

import  ExtendedRequestOptions  from '../helpers/extensions';

@Component(
    selector: 'app',
    template: `<router-outlet></router-outlet>`,
    directives: [
        ROUTER_DIRECTIVES
    ],
    viewProviders: [
        provide(Alerts,  useValue: [] )
    ],
    providers: [
        ROUTER_PROVIDERS,
        HTTP_PROVIDERS,
        provide(RequestOptions,  useClass: ExtendedRequestOptions )
    ]
)
@RouteConfig([
    path: '/user/:action',
    name: 'User',
    component: UserComponent,
    useAsDefault: true

])
export class AppComponent 

基本上,我提供了一个由每个 AlertComponent 使用的单例警报数组。

如果您想在指令之外使用它,您可以将 provide() 移动到提供程序(而不是 viewProviders),但如果不是,请保持简单并以这种方式限制它。

希望这可以帮助某人:)

【问题讨论】:

【参考方案1】:

公开它,以便它(作为一种单例)可供所有 来自 AppComponent 的路由/子组件。

或者还有其他更合适的方法吗?


像这样为AlertComponent 创建和引导服务

警报服务

import Injectable from '@angular/core';
import Subject from 'rxjs/Subject';
import 'rxjs/add/operator/share';

@Injectable()
export class AlertService 
  private _alerts: Array<Alert> = [];
  public alertsChange: Subject<Array<Alert>> = new Subject();

  public get alerts(): Array<Alert> 
    return this._alerts;
  

    add(alert: Alert) 
        this._alerts.push(alert);
        this.alertsChange.next(this._alerts);
    

    remove(index: number) 
        this._alerts.splice(index, 1);
        this.alertsChange.next(this._alerts);
    

    clear() 
        this._alerts = [];
        this.alertsChange.next(this._alerts);
    

引导警报服务

import bootstrap from '@angular/platform-browser-dynamic';
import YourApp from 'path/to/YourApp-Component';
import  AlertService from 'path/to/alert-service';

bootstrap(YourApp, [AlertService]);

警报组件

import  Component  from 'angular2/core';
import  Alert  from './model';
import  AlertService from 'path/to/alert-service';
@Component(
    selector: 'alerts',
    templateUrl: './alert/index.html'
)
export class AlertComponent 
    alerts: Array<Alert>;

    constructor(alertService: AlertService) 
      alertService.alertsChange.subscribe((moreAlerts: Array<Alert>) => 
         this.alerts = moreAlerts;
      )
    

所有路由/子组件

(样本):

import  Component from '@angular/core';
import  AlertService from 'path/to/alert-service';
@Component(
   template: `.....`
)
export class SampleComponent 

  constructor(public alerts: AlertService) 

  ngOnInit()
    this.alerts.add(new Alert('success', 'Success!'));
  

  ngOnDestroy()
    this.alerts.clear();
  


查看其他类似示例see this question

【讨论】:

这肯定行得通。谢谢!不过,蒂埃里·坦普利尔首先解决了标题问题,所以我会公平地把这个问题交给他。我认为像我这样的新人应该先看到他的答案,然后再实施更复杂的东西;例如,我选择适应蒂埃里的更简单的例子。当然也给你竖起大拇指。再次感谢! 不客气....你做了正确的事.... 【参考方案2】:

你需要使用ViewChild装饰器来引用它:

@Component(
)
export class AppComponent implements OnInit 
  @ViewChild(AlertComponent)
  _alert: AlertComponent;

  ngAfterViewInit() 
    // Use _alert
    this._alert.add(new Alert('success', 'Success!'));
  

@ViewChild 是在调用ngAfterViewInit 钩子方法之前设置的。

【讨论】:

感谢您的回答!有什么方法可以在两个或多个组件之间共享相同的 ViewChild/Directive 数据? 我不这么认为。在这种情况下,您需要利用可观察的共享服务。这样您就可以通知并被通知。有关详细信息,请参阅此链接:angular.io/docs/ts/latest/cookbook/…

以上是关于如何在另一个组件中获取指令/组件实例?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 React Hooks 在另一个组件中获取表单的输入值

从指令创建组件实例时如何等待 ngAfterViewInit() 运行?

如何在另一个样式组件中定位样式组件?

如何调用不在默认包中的Bean类

如何在@click 事件中获取组件实例?

如何在另一个站点中使用 NUXT 组件