Lazy loaded image
在Angular中创建可配模板的复用组件
Words 1349Read Time 4 min
2021-5-24
2025-7-1
type
status
date
slug
summary
tags
category
icon
password
在 Angular 中使用一些第三方 UI 库的时候,为了满足业务需求,经常会遇到需要通过 ng-template 来传递一些自定义的模板到第三方组件中的情况。比如 ngx-bootstrapTabs 组件,可以自定义 tab 的模板。
今天这篇文章会探究一下背后的原理,并且一步步实现一个类似功能的组件。

Counter 组件

首先创建一个最基本的 Counter 组件。这个组件展示当前的值并且可以执行递增和递减的操作。此外,还可以自定义初始值,并且在值更改时发出事件。
初始代码如下:
html 内容如下:

可配置模板

在 Angular 中,可以借助 ng-template 元素创建视图模板。 生成模板后,可以借助内容投影(content projection)将其传递给可重用组件,最终我们会通过下面的写法来使用组件:
通过上面的写法可以看出,每个视图模板都有自己的指令,因此我们可以区分每个 ng-template 属于组件的哪一部分。
首先来实现上面的三个指令,每个指令的内容都很简单:只需要公开一个对视图模板的引用。
接下来,我们可以在组件中使用 ContentChild 装饰器获取对视图模板的引用,第一个参数是指令的类名:
除了获取模板的 getter 之外,还有一些传递给视图模板的上下文对象的 getter,用来给 ng-template 传递数据。
最后在 html 模板中,我们通过 NgTemplateOutlet 指令,将视图模板渲染在组件的适当位置。在大多数第三方 UI 库中,如果没有传递自定义模板,就会使用默认的模板。
到这里我们就基本实现了一个可以自定义模板的可重用 Angular 组件。

扩展

ng-template

在上面的实现中,传递给 ng-templatecontext 返回了一个对象:
这个对象的 $implicit 属性就是 let-value 对应的变量。我们也可以传递多个对象,比如;
其中,let-value 没有赋值,会被自动赋值为 $implicit 的值。unit 对应返回的上下文对象中的 unit 属性。

使用 * Syntax

如果只需要传递一个值到 ng-template,可以使用更简化的语法:

string token

在给 ContentChild 装饰器传递第一个参数的时候,也可以传递一个字符串,这个字符串必须是唯一的模板引用变量。

结论

在 Angular 中,针对不同的需求场景可以有多种解决方案。如果我们想重用组件的布局,使用这种方式是比较合适的。如果仅仅是想通过内容投影来传递组件,那么使用组件惰性实例化可能是更好的方式。在实际开发中,需要根据不同的场景选择合适的实现。
参考链接:
上一篇
Angular使用ng-content进行内容投影
下一篇
Angular组件样式工作原理