Angular如何操作DOM?
deepthan opened this issue · 0 comments
deepthan commented
Angular不建议直接操作DOM元素,正如 ElementRef 函数的源码中介绍的一样:
export declare class ElementRef {
/**
* The underlying native element or `null` if direct access to native elements is not supported
* (e.g. when the application runs in a web worker).
*
* <div class="callout is-critical">
* <header>Use with caution</header>
* <p>
* Use this API as the last resort when direct access to DOM is needed. Use templating and
* data-binding provided by Angular instead. Alternatively you take a look at {@link Renderer}
* which provides API that can safely be used even when direct access to native elements is not
* supported.
* </p>
* <p>
* Relying on direct DOM access creates tight coupling between your application and rendering
* layers which will make it impossible to separate the two and deploy your application into a
* web worker.
* </p>
* </div>
* @stable
*/
nativeElement: any;
constructor(nativeElement: any);
}
export declare class ElementRef {
/**
* 如果不支持原生元素直接访问底层的本地元素或`null`
* (e.g. 当应用程序在一个网络工作者运行).
*
* <div class="callout is-critical">
* <header>请谨慎使用</header>
* <p>
* 当需要直接访问DOM时,使用此API作为最后的手段。 使用模板和
数据绑定由Angular提供。 或者,您可以查看{@link Renderer}
它提供的API即使在直接访问本地元素时也可以安全地使用
支持的。
* </p>
* <p>
* 依靠直接的DOM访问可以在应用程序和呈现之间建立紧密的耦合
* 层将使它不可能分开两个和部署你的应用程序到一个
* 网络工作者。
* </p>
* </div>
* @stable
*/
nativeElement: any;
constructor(nativeElement: any);
}
ElementRef 获取DOM (ref:参考)
在应用层直接操作 DOM,就会造成应用层与渲染层之间强耦合,导致我们的应用无法运行在不同环境,所以不能直接操作 DOM 元素。
在浏览器中,通过 ElementRef 我们就可以封装不同平台下视图层中的 DOM 元素,最后借助于 Angular 提供的强大的依赖注入特性,我们就可以轻松地访问到 DOM 元素。
// HTML
<div class='deep'>蛮子</div>
// TS
import { Component, ElementRef, ngAfterViewInit } from '@angular/core';
export class AppComponent {
constructor(private elementRef: ElementRef) { }
ngAfterViewInit(){
let divEle = this.elementRef.nativeElement.querySelector('deep');
console.log(divEle); ->打印出 '<div class='deep'>蛮子</div>'
}
}
内置属性装饰器 @ViewChild 改变其样式
// HTML
<div #deep>蛮子</div>
// TS
import { Component, ElementRef, ViewChild, ngAfterViewInit } from '@angular/core';
export class AppComponent {
@ViewChild('deep') willChangeDiv: ElementRef;
constructor(private elementRef: ElementRef) {}
ngAfterViewInit(){
this.willChangeDiv.nativeElement.style.backgroundColor = 'red';
}
}
renderer2 对象提供的 API 优雅改变样式
// HTML
<div #deep>蛮子</div>
// TS
import { Component, ElementRef, ViewChild, ngAfterViewInit, Renderer } from '@angular/core';
export class AppComponent {
@ViewChild('deep') willChangeDiv: ElementRef;
constructor(private elementRef: ElementRef) {}
ngAfterViewInit(){
this.renderer.setStyle(this.willChangeDiv.nativeElement, 'backgroundColor', 'red');
}
}
renderer2 提供了哪些方法?
export declare abstract class render2 {
/**
* This field can be used to store arbitrary data on this renderer instance.
* This is useful for renderers that delegate to other renderers.
*/
readonly abstract data: {
[key: string]: any;
};
abstract destroy(): void;
abstract createElement(name: string, namespace?: string | null): any;
abstract createComment(value: string): any;
abstract createText(value: string): any;
/**
* This property is allowed to be null / undefined,
* in which case the view engine won't call it.
* This is used as a performance optimization for production mode.
*/
destroyNode: ((node: any) => void) | null;
abstract appendChild(parent: any, newChild: any): void;
abstract insertBefore(parent: any, newChild: any, refChild: any): void;
abstract removeChild(parent: any, oldChild: any): void;
abstract selectRootElement(selectorOrNode: string | any): any;
/**
* Attention: On WebWorkers, this will always return a value,
* as we are asking for a result synchronously. I.e.
* the caller can't rely on checking whether this is null or not.
*/
abstract parentNode(node: any): any;
/**
* Attention: On WebWorkers, this will always return a value,
* as we are asking for a result synchronously. I.e.
* the caller can't rely on checking whether this is null or not.
*/
abstract nextSibling(node: any): any;
abstract setAttribute(el: any, name: string, value: string, namespace?: string | null): void;
abstract removeAttribute(el: any, name: string, namespace?: string | null): 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: 'window' | 'document' | 'body' | any, eventName: string, callback: (event: any) => boolean | void): () => void;
}