文章内容
2020/5/7 18:36:36,作 者: 黄兵
使用Angular 7-8 Renderer2进行DOM操作的示例
今天,我想与您分享一个最新发现,停止使用Angular ElementRef直接访问DOM,并选择Angular Renderer2方法来轻松操作DOM。在本文中,我们将介绍为什么最好使用Angular 7 Renderer2,然后我们将通过简单的示例了解如何使用Angular Renderer服务类来操作DOM元素。
总览
Renderer2类是Angular的即开即用功能,它提供了一种用于在运行时操作应用程序的UI呈现元素的抽象,而无需直接访问DOM。由于诸如XSS Attacks之类的安全性原因,这也是考虑的最佳方法,并且能够开发可在不具有直接DOM访问权限的各种平台(例如服务器,Web Worker或移动设备)上呈现的应用程序。
借助Angular 7 Renderer2服务类,您可以执行简单的DOM操作,也可以执行复杂的DOM操作。
使用Renderer2类,您可以添加和删除CSS类,样式,HTML属性。它可以用于在带有Angular 7 Renderer2类的父元素中追加或删除子元素。您可以轻松地将HTML注释添加到DOM的任何父元素。您可以使元素侦听某些已定义的事件。
让我们跳到这些示例,以使事情更加清楚,并详细了解Angular 7和8 Renderer2服务类的优点。
遵循错误的方法
在转到Renderer2示例之前,我们首先来看一个应避免的操纵应用程序DOM元素的脆弱方法。
此方法基于@angular/core提供的ElementRef,以直接访问元素并使用Angular操作DOM。
如果选择用于操纵DOM的指令,则很可能会直接使用nativeElement,如下所示:
import { Directive, ElementRef, OnInit } from '@angular/core';
@Directive({
selector: '[textDanger]'
})
export class textDangerDirective implements OnInit {
constructor(private elRef: ElementRef) { }
ngOnInit() {
this.elRef.nativeElement.style.color = 'red';
}
}Angular文档对ElementRef的评价:
当需要直接访问DOM时,请使用此API作为最后的手段。允许直接访问DOM可以使您的应用程序更容易受到XSS攻击。仔细检查代码中对ElementRef的任何使用。改用Angular提供的模板和数据绑定。另外,您可以看一下Renderer,它提供了即使不支持直接访问本机元素也可以安全使用的API。
依靠直接DOM访问会在您的应用程序和呈现层之间建立紧密的耦合,这将使得不可能将两者分开并将您的应用程序部署到Web Worker中。
如何使用Angular Renderer进行DOM操作
在自定义指令中使用Renderer2更方便,因为Angular指令是负责修改元素的主要逻辑构建块。
在这里,我们将提供一个简单的示例,该示例使用服务中的setStyle()方法Renderer2来更改前一个不良示例中具有自定义指令的元素的CSS颜色属性。
使用此命令生成定制指令。
ng generate directive textDanger
然后,text-danger.directive.ts添加。
import { Directive, Renderer2, ElementRef, OnInit } from '@angular/core';
@Directive({
selector: '[appTextDanger]'
})
export class textDangerDirective implements OnInit {
constructor(private renderer: Renderer2, private elRef: ElementRef) {}
ngOnInit() {
this.renderer.setStyle(this.elRef.nativeElement, 'color','red');
}
}然后,您需要将此指令添加到您的任何模板元素中,并且在按以下方式呈现时将应用红色属性。
<h1 appTextDanger>
Hello World!
</h1>您会注意到通过Angular Renderer2服务而不是直接访问DOM元素来操作DOM是多么简单和干净。现在让我们看看下面的其他有用方法。
createElement / appendChild / createText
这允许将新创建的DOM元素附加到任何现有元素中。在此示例中,我们将在其中创建一个li元素和一个文本节点。然后,将文本节点放入新创建的节点中li,最后将li元素添加到具有我们指令的元素(即ultag元素)的后面。
constructor(private renderer: Renderer2, private elRef: ElementRef) {}
ngOnInit() {
const li = this.renderer.createElement('li');
const text = this.renderer.createText('New li element from renderer');
this.renderer.appendChild(li, text);
this.renderer.appendChild(this.elRef.nativeElement, li);
}当呈现模板并将指令应用于ul元素时,我们将得到此结果。
<ul>
<li>New li element from renderer</li>
</ul>setAttribute / removeAttribute
使用Renderer2服务中的setAttribute()和removeAttribute()从元素中设置或删除属性。
@Directive({
selector: '[defaultValue]'
})
export class DefaultInputValueDirective {
constructor(private elRef: ElementRef, private renderer: Renderer2) {
}
@HostListener('mouseover')
onMouseOver() {
this.renderer.setAttribute(this.elRef.nativeElement, 'value', 'Enter a Value');
}
@HostListener('mouseleave')
onMouseLeave() {
this.renderer.removeAttribute(this.elRef.nativeElement, 'value');
}
} 将指令应用于输入时,将鼠标悬停在DOM中即可获取此源代码。
<input type="text" value="Enter a Value ">addClass / removeClass
addClass()和removeClass()都用于一个CSS类添加到一个元件或将其删除。让我们看下面的示例,该示例允许使用hl-text CSS类突出显示文本。
@Directive({
selector: '[hlOnMouseOver]'
})
export class HlOnMouseOverDirective {
constructor(private elRef: ElementRef, private renderer: Renderer2) {
}
@HostListener('mouseover')
onMouseOver() {
this.renderer.addClass(this.elRef.nativeElement, 'hl-text');
}
@HostListener('mouseleave')
onMouseLeave() {
this.renderer.removeClass(this.elRef.nativeElement, 'hl-text');
}
}鼠标悬停时,CSS类将应用于具有此伪指令的元素,并且在呈现模板时,您将获得此源代码。
<div class="hl-text"> Highlighted Text ! </div>setStyle / removeStyle
我们已经setStyle()在上面的示例中介绍了该方法。对于,removeStyle()您将必须提供要从中删除指定样式的元素。
@Directive({
selector: '[removeTextDanger]'
})
export class removeTextDangerDirective implements OnInit {
constructor(private renderer: Renderer2, private elRef: ElementRef) {}
ngOnInit() {
this.renderer.removeStyle(this.elRef.nativeElement, 'color','red');
}
}removeChild
它删除父元素内的子元素。您需要做的就是提供父元素和要从DOM中删除的子元素。
@Directive({
selector: '[removeChild]'
})
export class RemoveChildDirective {
constructor(private elRef: ElementRef, private renderer: Renderer2) {
}
p = this.renderer.createElement('p');
text = this.renderer.createText('Hello World !');
@HostListener('mouseover')
onMouseOver() {
this.renderer.appendChild(this.p, this.text);
this.renderer.appendChild(this.elRef.nativeElement, this.p);
}
@HostListener('mouseleave')
onMouseLeave() {
this.renderer.removeChild(this.elRef.nativeElement, this.p);
}
}在鼠标悬停时,该p元素将作为子元素添加到具有此伪指令的元素中,并在鼠标离开时被删除。
setProperty
在setProperty()允许设置一个属性具有值给一个元素。例如,您可以使用以下代码将alt属性添加到DOM中的图像元素。
@Directive({
selector: '[imgAlt]'
})
export class ImageAltdDirective {
constructor(private renderer: Renderer2, private elRef: ElementRef) {}
ngOnInit() {
this.renderer.setProperty(this.elRef.nativeElement, 'alt', 'image description');
}
}写在最后
在本文中,我们通过一些清晰的示例逐步展示了Angular 7和8 Renderer2类的基本用法,以及如何使用Renderer2服务类而不是ElementRef来简单地操作DOM元素。
最后,请从现在开始停止使用ElementRef并使用Angular Renderer。
请参阅API文档以了解有关Rendere2可用方法的更多信息。
原文地址:DOM Manipulation Using the Angular 7-8 Renderer2 with Examples

评论列表