探索使用 ViewContainerRef 的 Angular DOM 操控技术
https://indepth.dev/posts/1052/exploring-angular-dom-manipulation-techniques-using-viewcontainerref
每当我阅读关于在 Angular 中处理 DOM 的文章的时候,我总是看到这些类型中的某些被提到:
- ElementRef
- TemplateRef
- ViewContainerRef
- ......
不幸的是,尽管它们在 Angular 的文档中被说明了,我还是没有找到对概念模型进行全面说明的文档和示例,以及它们是如何被组合使用的。本文尝试说明 Angular 的概念模型。
如果你正在寻找在 Angular 中使用 Renderer 和 View 来操作 DOM 的深入讨论,请查阅 my talk at NgVikings。或者阅读深入讨论动态 DOM 操控的文章 Working with DOM in Angular: unexpected consequences and optimization techniques
如果原来使用过 angular.js,你就会知道,处理 DOM 是非常简单的事情。Angular 将 DOM 元素 element 传递给 link() 函数,你可以查询组件模板内的任何节点,增加或者删除子节点,修改样式等等。不过,这种方式有一个重要的缺陷 - 它紧密耦合到浏览器平台上。
新的 Angular 运行在多种平台上 - 浏览器,移动平台,或者运行在 Web worker 上。所以需要一个抽象层来从平台特定的 API 中抽象出来框架的接口。在 Angular 中,这些抽象通过这些引用类型表示:
- ElementRef
- TemplateRef
- ViewRef
- ComponentRef
- ViewContainerRef
在本文中,我们将深入演练这些抽象类型中每一个,并展示如何使用它们来操控 DOM。
@ViewChild
在开始说明这些 DOM 抽象之前,让我们先理解一下,如何在 Component/Directive 类中访问这些抽象。Angular 提供了被称为 DOM query 的机制。它使用了 @ViewChild 和 @ViewChildren 装饰器。两种的行为类似,只是前一种只返回一个引用,而后一种以 QueryList 对象的形式返回多个引用。在本文的示例中,我将主要使用 ViewChild 装饰器,并忽略这个 @ 符号。
一般来说,这些装饰器与 template reference variables 配套使用,template reference variable 是用来在模板中简单地引用 DOM 元素的方式。你可以想象它类似于 html 元素所提供的 id 特性。使用 template reference variable 来标记一个 DOM 元素,然后在类中使用 ViewChild 装饰器来查询到它。下面是一个基本的示例:
@Component({
selector: 'sample',
template: `
<span #tref>I