在《Angular开发实践(六):服务端渲染》这篇文章的最后,我们也提到了在服务端渲染
中需要牢记的几件事件,其中就包括不要使用window
、 document
、 navigator
等浏览器特有的类型以及直接操作DOM元素。
这样就引出了 Angular 主要特性之一:横跨所有平台。通过合适的方法,使用 Angular 构建的应用,可复用在多种不同平台的应用上 —— Web、移动 Web、移动应用、原生应用和桌面原生应用。
为了能够支持跨平台,Angular 通过抽象层封装了不同平台的差异。比如定义了抽象类 Renderer2 、抽象类 RootRenderer 等。此外还定义了以下引用类型:ElementRef、TemplateRef、ViewRef 、ComponentRef 和 ViewContainerRef 等。通过 模板变量
、@ViewChild
等方法获取DOM元素。
为了演示,先定义一个组件DemoComponent:
1 | import { AfterViewInit, Component, ElementRef, Renderer2, ViewChild } from '@angular/core'; |
获取组件中的div
在Angular应用中不应该通过原生 API 或者 jQuery 来直接获取DOM元素:
1 | let element1 = document.getElementById("demoDiv"); // jQuery获取: $('#demoDiv') |
而是应该通过Angular提供的方法来获取DOM元素:
模板变量
1 | <div id="demoDiv" #demoDiv>this is DIV!</div> |
在组件模板中,我们在 div 上定义了 #demoDiv 的模板变量,那么 demoDiv 就等于该 div 的 DOM 对象,因此我们可以通过 demoDiv.id
直接获取 div 的 id。
@ViewChild
1 | @ViewChild('demoDiv') demoDiv: ElementRef; // @ViewChild通过模板变量名获取 |
在组件类中,我们通过 @ViewChild 获取到包装有 div 的 DOM 对象的 ElementRef 对象,ElementRef 定义如下:
1 | class ElementRef<T> { |
因此我们可以在 ngAfterViewInit 中通过 this.demoDiv.nativeElement 获取到该 div 的 DOM 对象,然后获取元素的id。
操作组件中的div
在上面通过几种方式获取到 div 的 DOM 对象,那么我们要如果对它进行操作呢(设置样式、属性、插入子元素等)?通过原始API 或者 jQuery 肯定是不允许的了。
这样我们就引出Angular抽象类 Renderer2
来对元素进行设置样式、属性、插入子元素等操作。
Renderer2 的定义如下:
1 | class Renderer2 { |
因此,我们想改变 div 的背景色,就可以这样做:
1 | ngAfterViewInit() { |