Angular 动态创建嵌入式视图

Photo by James Coleman on Unsplash

声明

本篇为 Angular 中相对高级的教程,涉及到了结构性指令、生命周期重要概

念。建议这块不熟悉的读者可以看看 Angular 结构型指令 NgIf 原理 ,这篇文

章中我结合源码对 Angular 指令中的黑魔法做了解析。

视图

Angular 中视图是一个重要的概念。从源码角度来看,Angular 中的视图是包

含页面结点(DOM)与在此之上的绑定(数据)的结构体,通过视图 Angular

将变量与页面结点进行关联,从而可以在执行变更检测等操作时实现控制层数

据与页面结点的联动,这也也是绑定 (binding)这一术语的由来。

正是因为视图是 Angular 的核心所在,在 Angular 中想要创建一个页面片段

最好的方式也是把这个页面片段当做一个视图。由内置指令 NgIf、NgFor 的实

现可知,我们可以利用模板 <ng-tempalte> 来创建这个页面片段的视图,这个

视图在 Angular 中又被称作嵌入式视图。换句话说,嵌入式视图本身就是视

图,特殊之处在它是由模板创建而来罢了。

嵌入式视图的创建方法有两种,一种办法是直接利用 Angular 内置指令。这种

方法直接在组件对应模板上就能完成嵌入式视图的创建。缺点是使用场景比较

局限,只能作用于组件模板上。另一种方法是直接在组件的控制层中利用内置

对象完成嵌入式视图的创建。这种方法相对麻烦一点,但胜在灵活,在组件和

指令中都能使用。

简单但笨重

Angular 提供了一个 ngTemplateOutlet 指令。我们只要将这个指令作用与某

个元素(一般来说是容器元素 <ng-container>),就会自动在这个元素下创建

一个嵌入式视图。

如上所示,我们可以在 NgTemplateOutlet 中 context 输入变量中指定我们的

上下文环境变量。上下文环境变量通俗的说就是一组参数。我们可以在模板中

使用 let 语法来接受上下文环境信息。

这里模板中 let-name = “localSk” 表明模板内建了一个 name 变量,用于接受

NgTemplateOutlet 传过来的上下文环境变量中 locakSk 的信息。

繁琐但灵活

采用 Angular 内置类 viewContainerRef ( 视图容器引用)与 templateRef

( 视图模板引用 )创建嵌入式视图相对比较繁琐,但是可以同时作用于组件与

指令,因此在灵活性上更胜一筹。

作用于指令时,可通过依赖注入的方式得到指令作用宿主 viewContainerRef

和 templateRef 。然后通过 viewContainerRef 的 createEmbeddedView 方

法传入 templateRef 和 上下文环境变量来创建嵌入视图。

一旦传入上下文环境变量,你就可以在 ng-tempalte 中使用 let 语法绑定这个

环境变量,并在子元素中使用它。

作用于组件时,唯一需要注意的是,调用 createEmbedded 方法的生命周期要

在 ngAfterViewInit 之后。这是因为 ViewChild 修饰符获取元素的引用,需要

在组件初始化完成后才能生效。其他的用法和做用于指令时相同。

万剑归宗

两种方式虽然形式不同,但都本着一个逻辑。即在视图容器中创建一个视图模

板,并通过某种方法将上下文参数带给后者。理解了这点就不难做到灵活使用

它们。

参考链接

NgTemplateOutlet —— 官方文档

发表评论

电子邮件地址不会被公开。 必填项已用*标注