这是您需要了解的有关Angular中的动态组件的知识( 二 )


就像在中一样 , 新框架中的每个组件都是某个模块的一部分 。组件本身并不存在 , 如果要使用其他模块中的组件 , 则必须导入该模块:
@({ //withlike // ngIf, ngFor,etc. : [], ... })class{}
反过来 , 如果一个模块要提供某些组件供其他模块组件使用 , 则必须导出这些组件 。这是的工作方式:
const : [] = [ , , , NgIf, ... ]; @({ : [, ...], : [, ...], ... })class{ }
因此 , 每个组件都绑定到一个特定的模块 , 并且您不能在不同的模块中声明相同的组件 。如果这样做 , 将会出现错误:
Type X is part of theof 2 : ...
编译应用程序时 , 它将获取在模块的中定义或在组件模板中找到的组件 , 并为其生成组件工厂 。您可以在“源”选项卡中看到这些工厂:

这是您需要了解的有关Angular中的动态组件的知识

文章插图
在上一节中 , 我们确定了如果可以访问组件工厂 , 则可以使用它来创建组件并插入视图中 。每个模块都为其所有组件提供了便利的服务 , 以使组件出厂 。该服务是lver。因此 , 如果您在模块上定义了并希望保留其工厂 , 则可以从属于该模块的组件中使用此服务:
class{ ( : lver) { // now the `f`ato the cmpconst f = this..ory(); }
仅当两个组件都在同一模块中定义或导入具有已解决组件工厂的模块时 , 此方法才有效 。
动态模块加载和编译
但是 , 如果您的组件是在另一个模块上定义的 , 而您实际上并不需要该组件 , 那么该组件又该如何加载呢? 我们能做到这一点 。这将类似于路由器使用配置选项所做的事情 。
有两种方法可以在运行时加载模块 。第一个是使用提供的er。如果您将用作加载程序 , 则路由器将其用于加载子路由 。它具有一个公共方法加载 , 该加载将模块加载到浏览器并编译该模块及其中声明的所有组件 。此方法采用具有模块和导出名称的文件路径 , 并返回 :
.load('path/to/file#')
如果未指定导出名称 , 则加载的文件将使用默认的导出名称 。要注意的另一件事是er需要进行一些注入的DI设置 , 因此您应将其定义为这样的提供程序:
: [ { : r, : er } ]
您当然可以指定要提供的任何令牌 , 但是路由器模块使用r , 因此使用相同的方法可能是一件好事 。
因此 , 这是加载模块并获取组件工厂的完整代码:
@({ : [ { : r, : er } ] })class t { ( : ,: r) { } () { this. .load('app/t.#') .then(() => { const= .(this.); const r = r; const= r.ory(); //aandit to the viewconst= .(this.); this..(.); }) } }
但是使用er存在一个问题 。在后台  , 它使用编译器的方法 。此方法仅为在模块的中声明或在组件模板中找到的组件创建工厂 。但是 , 如果您不想将组件声明为入口组件怎么办? 有一个解决方案-自己加载模块并使用方法 。它为模块上的所有组件生成工厂 , 并将它们作为的实例返回:
class{ : []; : ;
这是完整的代码 , 显示了如何自己加载模块并访问所有组件工厂的方法:
() { .('app/t.').then(() => { (.) .then(() => { const m = ..(this.); const= [0]; const cmp = .(this., [], null, m); }) }) }
请记住 , 这种方法使用了不支持作为公共API的编译器 。这是文档所说的 :
此列表中的一个有意遗漏的是@/  , 它目前被认为是低级api , 并且可能会进行内部更改 。这些更改不会影响使用更高级别的api(命令行界面或通过@/ -b??-进行的JIT编译)的任何应用程序或库 。只有非常特定的用例才需要直接访问编译器API(主要是IDE , lint等的工具集成) 。如果您正在从事这种集成 , 请首先与我们联系 。动态创建组件