在项目中有时候需要直接操作DOM,但是这样直接访问 DOM 会导致应用很容易受到在 XSS 攻击。所以并不建议直接访问 DOM。
在Angular 访问DOM 需要使用 Render2 来实现自定义渲染。
Renderer2类是Angular以服务的形式提供的抽象类,允许操作当前应用的元素,而不用直接访问最原始的DOM元素。
官方API
abstract class Renderer2 {
abstract data: {
...}
destroyNode: ((node: any) => void) | null
abstract destroy(): void
abstract createElement(name: string, namespace?: string): any
abstract createComment(value: string): any
abstract createText(value: string): any
abstract appendChild(parent: any, newChild: any): void
abstract insertBefore(parent: any, newChild: any, refChild: any): void
abstract removeChild(parent: any, oldChild: any, isHostElement?: boolean): void
abstract selectRootElement(selectorOrNode: any, preserveContent?: boolean): any
abstract parentNode(node: any): any
abstract nextSibling(node: any): any
abstract setAttribute(el: any, name: string, value: string, namespace?: string): void
abstract removeAttribute(el: any, name: string, namespace?: string): void
abstract addClass(el: any, name: string): void
abstract removeClass(el: any, name: string): void
abstract setStyle(el: any, style: string, value: any, flags?: RendererStyleFlags2): void
abstract removeStyle(el: any, style: string, flags?: RendererStyleFlags2): void
abstract setProperty(el: any, name: string, value: any): void
abstract setValue(node: any, value: string): void
abstract listen(target: any, eventName: string, callback: (event: any) => boolean | void): () => void
}
使用一些常用的方法
创建一个Demo组件
使用命令:
ng g c operatingDOM
创建成功
wujiayudeMacBook-Pro:pages wjy$ ng g c operatingDOM
CREATE src/app/pages/operating-dom/operating-dom.component.less (0 bytes)
CREATE src/app/pages/operating-dom/operating-dom.component.html (32 bytes)
CREATE src/app/pages/operating-dom/operating-dom.component.spec.ts (671 bytes)
CREATE src/app/pages/operating-dom/operating-dom.component.ts (297 bytes)
UPDATE src/app/pages/pages.module.ts (2371 bytes)
在组件中注入 Render2
修改组件的类文件如下:
import {
Component, OnInit, Renderer2} from '@angular/core';
@Component({
selector: 'app-operating-dom',
templateUrl: './operating-dom.component.html',
styleUrls: ['./operating-dom.component.less']
})
export class OperatingDOMComponent implements OnInit {
constructor(private render2: Renderer2) {
}
ngOnInit() {
}
}
创建一个元素,将这个元素添加到组件模版已有的元素中
修改组件的模版文件如下:
<nz-divider nzText="Render2 操作DOM"></nz-divider>
<div #demo></div>
<button nz-button (click)="restDemoApi1()">createElement</button>
按钮的点击事件如下:
import {
Component, ElementRef, OnInit, Renderer2, ViewChild} from '@angular/core';
@Component({
selector: 'app-operating-dom',
templateUrl: './operating-dom.component.html',
styleUrls: ['./operating-dom.component.less']
})
export class OperatingDOMComponent implements OnInit {
@ViewChild('demo') demoDom: ElementRef;
constructor(private render2: Renderer2) {
}
ngOnInit() {
}
// createElement & appendChild & createText
public restDemoApi1(): void {
const divEle = this.render2.createElement('div');
const textEle = this.render2.createText('hello Render2');
this.render2.appendChild(divEle, textEle);
this.render2.appendChild(this.demoDom.nativeElement, divEle);
}
}
在这个方法中,通过 createElement 创建了一个 div 的元素,并通过 createText 创建了以一段文本节点, 将这段文本节点 通过 appendChild方法添加刚刚创建的 div 元素中,这里的div作为父元素, 文本节点作为子元素。并将添加了 文本节点 的div元素 添加到模版已经有的 demo 元素中。
从而点击的效果如下:
为DOM元素添加/删除 Attribute
在这里为之前的 div 元素增加 aria-hidden=“true” 的Attribute。
添加Attribute
修改模版文件:
<h1>Render2 操作DOM</h1>
<nz-divider nzText="创建一个DOM"></nz-divider>
<div #demo></div>
<button nz-button (click)="restDemoApi1()">createElement</button>
<nz-divider nzText="添加"></nz-divider>
<button nz-button (click)="handleSetAttribute()">添加特性</button>
修改类文件:
import {
Component, ElementRef, OnInit, Renderer2, ViewChild} from '@angular/core';
import {
NzNotificationService} from 'ng-zorro-antd';
@Component({
selector: 'app-operating-dom',
templateUrl: './operating-dom.component.html',
styleUrls: ['./operating-dom.component.less']
})
export class OperatingDOMComponent implements OnInit {
@ViewChild('demo') demoDom: ElementRef;
constructor(private render2: Renderer2, private notification: NzNotificationService) {
}
ngOnInit() {
}
// createElement & appendChild & createText
public restDemoApi1(): void {
const divEle = this.render2.createElement('div');
const textEle = this.render2.createText('hello Render2');
this.render2.appendChild(divEle, textEle);
this.render2.appendChild(