Angular2将组件渲染到页面主体

10
假设我有一个 Angular2 组件 <my-button>,并且我想要为渲染下拉菜单提供选项的输入,当点击按钮时该下拉菜单会显示出来。我把菜单组件命名为 <my-menu>,如果有传入选项,它就会在 <my-button> 的模板中有条件地呈现。
也许我可以将 <my-menu> 绝对定位在 <my-button> 内,以实现期望的定位效果。但是,可能由于包含元素具有 overflow:hidden 属性,这样会剪裁 <my-menu>。因此,我需要在 <body> 中呈现 <my-menu> 并将其绝对定位到 <my-button> 上。
即使将其放置在 <my-button> 的模板内,是否有一种方法可以将 <my-menu> 渲染到 <body> 中呢?
谢谢!
4个回答

7

您可以这样做,但是这很复杂。

  1. Add your dynamic component to module declarations and entryComponents
  2. Get reference to root ViewContainerRef injecting it to your application component.
  3. Get reference to ComponentFactoryResolver, also using injection.
  4. Use something like this:

    private resolverFactory:ComponentFactoryResolver;
    private viewContainer:ViewContainerRef;
    
    var compFactory:ComponentFactory<Frame> = this.resolverFactory.resolveComponentFactory(Frame);
    
    var cmpRef:ComponentRef<Frame> = this.viewContainer.createComponent(compFactory, this.viewContainer.length);
    
  5. Removing component:

    cmpRef.destroy();
    

1
没有,不可以。
你可以在你的AppComponent之外引导一个组件,并使用共享服务进行通信。
有一些关于动态创建组件作为AppComponent的同级讨论,这些讨论在https://github.com/angular/angular/issues/9293中讨论,但目前还不清楚它是否会被采纳、如何采纳以及何时采纳。

AppComponent 内部渲染可能是可以的,没有必要引导额外的东西。但是你能详细说明一下如何使用共享服务进行通信吗?主要是,如何在组件树上截然不同的位置呈现菜单和按钮,然后将两者关联起来? - Comptonburger
1
应该在https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service中解释所有内容。 - Günter Zöchbauer
@GünterZöchbauer,正如我在下面的评论中所述,许多样板和普遍功能需要能够向<body>添加任意组件:模态框、工具提示、类似于growl的通知、菜单等,您有任何想法如何在2.0.x(GA)中实现这些功能吗? - AndyPerlitch

1
如果您想有条件地加载组件,可以使用ComponentResolverFactory。
您只需要拥有一个viewContainerRef实例,并在需要的地方使用编译器更新它即可。
我建议为您想要动态加载的所有组件创建一个单独的模块,并异步加载它们。
也许下面的答案可以更好地帮助您。 动态加载组件

1

是的,你可以。由于你没有提供代码,我无法给你一个更新的示例。然而,当我构建模态系统时,我使用了这个作为基础: https://github.com/shlomiassaf/angular2-modal

当我们最初引入它时,它不是非常可重用的,但有一种方法可以通过 ApplicationRef 获取根节点。(这是在 Angular 2 beta 8 左右。)

这绝对是可行的。

更新: 您可以使用 ApplicationRef 来获取要注入的位置,并使用 DynamicComponentLoader 注入您的新组件。使用以下行作为您的 hostLocation (DynamicComponentLoader 的 loadIntoLocation 方法中的第二个参数) 将元素放置在您的应用程序组件后面:

this.appRef['_rootComponents'][0].location

appRef是传递到我的组件构造函数中的ApplicationRef的引用。

您可以尝试使用beta .8之后发布的其他元素或方法来获得所需的效果。

这是另一个有很多示例的好网站:https://medium.com/tixdo-labs/angular-2-dynamic-component-loader-752c3235bf9#.x913qdh4u


DynamicComponentLoader 在 Angular2 GA 中是否仍然可用?我找不到相关文档,它似乎与 ComponentResolver 有些关联,而后者已被完全弃用,推荐使用 Compiler - AndyPerlitch
实际上看起来你提供的 medium.com 博客链接已经无法在 angular2 中使用。 - AndyPerlitch
@AndyPerlitch - 这就是为什么我标记了我使用的 beta 版本的示例。我认为我仍然能够在 RC 1 中完成它,但我不得不直接链接到一个比主包中暴露的更深层次的文件,这是 Angular 团队建议不要做的。自从 RC 1 以来,我还没有尝试过,但我可以在最终版本中尝试一下。 - ps2goat
谢谢@ps2goat。我确认DynamicComponentLoader甚至Compiler#compileComponent已被弃用。必须有一种方法直接将组件附加到body中...除了OP所描述的菜单之外,还有许多需要的用例:模态框,弹出式通知,弹出层,工具提示... - AndyPerlitch

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