简体   繁体   English

Angular 2+:使用服务共享组件参考

[英]Angular 2+: share component reference using a service

I have an Angular component called "tree". 我有一个名为“ tree”的Angular组件。 What I want is to call methods on tree from any other component in my app. 我想要从应用程序中的任何其他组件调用树上的方法。 There will only be one tree in my entire app at any time. 任何时候我的整个应用程序中只有一棵树。 Is it ok to create the component in the place I want to view it and share the componentRef using a service this way: 是否可以在我要查看的位置创建组件并使用服务通过以下方式共享componentRef:

export class AppComponent implements OnInit {

    @ViewChild("tree") treeComponent: TreeComponent;

    constructor(private treeService: TreeService) { }

    ngOnInit() {
        this.treeService.setTreeReference(this.treeComponent);
    }

}

Then I could call it this way: 然后我可以这样称呼它:

export class OtherComponent {

    constructor(private treeService: TreeService) { }

    getActiveNode() {
        return this.treeService.treeReference.getActiveNode();
    }

}

Is this a good practice in Angular2+ or generally in MVC? 这是Angular2 +还是MVC的良好做法?

Edit1: I forgot to specify that I don't have access to the TreeComponent code as it is imported from a library. Edit1:我忘记指定我无权访问TreeComponent代码,因为它是从库中导入的。

This is not the recommended approach to shared service architecture. 这不是推荐的共享服务体系结构方法。 The reason is because this creates tight coupling between the components. 原因是因为这在组件之间建立了紧密的耦合。 All consumers need to know the specific implementation details of both the tree service and the tree component, if either needs to change, every consumer will break. 所有使用者都需要知道树服务和树组件的具体实现细节,如果其中任一者需要更改,则每个使用者都会崩溃。 The way it should be exposed is a simple service api that exposes a way to set and subscribe to the shared data. 应该公开的方式是一个简单的服务api,它公开了一种设置和订阅共享数据的方式。 This means you only need to maintain your service's API and then the implementation itself can be quite flexible. 这意味着您只需要维护服务的API,然后实现本身就可以非常灵活。 It also makes your code much easier to read and more obvious what's going on. 这也使您的代码更易于阅读,并且更清楚显示正在发生的事情。 Someone poking their head in might find it kind of mysterious that that app component is setting a tree reference onIinit and wouldn't understand. 有人戳了一下脑后,可能会发现该应用程序组件在Iinit上设置树引用,这是一种不可理解的感觉。 This solution also doesn't really scale very well as you have more needs of similar functions 由于您需要更多类似功能,因此该解决方案的扩展性也不太好

This is how it would be achieved: 这样可以实现:

@Injectable()
export class TreeService {
  private activeNodeSubject: BehaviorSubject<any> = new BehaviorSubject(null);
  activeNode$ = this.activeNodeSubject.asObservable();
  setActiveNode(node) {
      this.activeNodeSubject.next(node);
  }
}

then in tree component, you call setActiveNode every time it changes, and all consumers subscribe to activeNode$ to always know which node is active. 然后在树组件中,每次更改时都调用setActiveNode,并且所有使用者都订阅了activeNode $以始终知道哪个节点处于活动状态。

There multiple ways to achieve what you are looking for: 有多种方法可以实现您想要的目标:

  • Event driven 事件驱动

You can dispatch events to your "tree" component by using the mediator pattern. 您可以使用调解器模式将事件调度到“树”组件。 You can find multiple libs for that. 您可以为此找到多个库。 For instance: EventEmitter2 例如: EventEmitter2

  • Inject the component has value 注入组件具有价值

You can inject the component itself has value and then use it everywhere on your application. 您可以注入组件本身的价值,然后在应用程序中的任何地方使用它。 An example of an injection factory . 一家注塑厂例子

Best, José 最好,何塞

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM