Home  >  Article  >  Web Front-end  >  Angular development practice (7): Cross-platform operation of DOM and renderer Renderer2

Angular development practice (7): Cross-platform operation of DOM and renderer Renderer2

不言
不言Original
2018-04-02 15:11:414384browse

In "Angular Development Practice (6): Server-side Rendering"At the end of this article, we also mentioned several events that need to be kept in mind in Server-side rendering, These include not using browser-specific types such as window, document, navigator and directly manipulating DOM elements.

This brings us to one of Angular’s ​​main features: across all platforms. With the right approach, applications built using Angular can be reused on multiple different platforms - web, mobile web, mobile apps, native apps, and desktop native apps.

In order to support cross-platform, Angular encapsulates the differences of different platforms through abstraction layers. For example, abstract class Renderer2, abstract class RootRenderer, etc. are defined. In addition, the following reference types are defined: ElementRef, TemplateRef, ViewRef, ComponentRef, ViewContainerRef, etc. Obtain DOM elements through template variables, @ViewChild and other methods.

For demonstration, first define a component DemoComponent:

import { AfterViewInit, Component, ElementRef, Renderer2, ViewChild } from '@angular/core';

@Component({
    template: `
        <p id="demop" #demop>this is p!</p>
        p的id:{{demop.id}} <!-- p的id:demop -->
    `
})
export class DemoComponent implements AfterViewInit {
    @ViewChild(&#39;demop&#39;) demop: ElementRef; // @ViewChild通过模板变量名获取

    constructor(private renderer: Renderer2) {
    }

    ngAfterViewInit() {
        console.log(&#39;p的id:&#39; + this.demop.nativeElement.id); // p的id:demop
        this.renderer.setStyle(this.demop.nativeElement, &#39;background-color&#39;, &#39;red&#39;); // 通过Renderer2设置p的css样式background-color
    }
}

Get the p in the component

In Angular applications, DOM elements should not be obtained directly through native API or jQuery:

let element1 = document.getElementById("demop"); // jQuery获取: $('#demop')

Instead, you should get the DOM element through the method provided by Angular:

Template variable

a728b34f8c39ac4b8264402fa7a79be6this is p!94b3e26ee717c64999d7867364b1b4a3
p的id:{{demop.id}} 56a354faacebef689e1d2dd71ed7d1a6

In the component template, we define the template of #demop on p variable, then demop is equal to the DOM object of p, so we can directly obtain the id of p through demop.id.

@ViewChild

@ViewChild(&#39;demop&#39;) demop: ElementRef; // @ViewChild通过模板变量名获取

ngAfterViewInit() {
    console.log(&#39;p的id:&#39; + this.demop.nativeElement.id); // p的id:demop
}

In the component class, we obtain the ElementRef object that wraps the DOM object of p through @ViewChild. The ElementRef is defined as follows:

class ElementRef8742468051c85b06f0a0af9e3e506b5c {
  constructor(nativeElement: T)
  nativeElement: T
}

So we can Get the DOM object of p through this.demop.nativeElement in ngAfterViewInit, and then get the id of the element.

p in the operation component

has obtained the DOM object of p through several methods above, so how do we operate on it (setting styles, attributes, inserting sub-elements, etc.) ? Via raw API or jQuery is definitely not allowed.

In this way, we introduce the Angular abstract class Renderer2 to set styles, attributes, insert sub-elements and other operations on elements.

Renderer2 is defined as follows:

class Renderer2 {
    get data: {...}
    destroyNode: ((node: any) => void) | null
    destroy(): void
    createElement(name: string, namespace?: string | null): any // 创建元素
    createComment(value: string): any // 创建注释元素
    createText(value: string): any // 创建文本元素
    appendChild(parent: any, newChild: any): void // 添加子元素(在最后)
    insertBefore(parent: any, newChild: any, refChild: any): void // 添加子元素(在最前)
    removeChild(parent: any, oldChild: any): void // 移除子元素
    selectRootElement(selectorOrNode: string | any): any // 获取根元素
    parentNode(node: any): any // 获取父元素
    nextSibling(node: any): any // 获取下一个兄弟元素
    setAttribute(el: any, name: string, value: string, namespace?: string | null): void // 设置属性
    removeAttribute(el: any, name: string, namespace?: string | null): void // 移除属性
    addClass(el: any, name: string): void // 添加样式类
    removeClass(el: any, name: string): void // 移除样式类
    setStyle(el: any, style: string, value: any, flags?: RendererStyleFlags2): void // 设置样式
    removeStyle(el: any, style: string, flags?: RendererStyleFlags2): void // 移除样式
    setProperty(el: any, name: string, value: any): void // 设置DOM对象属性,不同于元素属性
    setValue(node: any, value: string): void // 设置元素值
    listen(target: &#39;window&#39; | &#39;document&#39; | &#39;body&#39; | any, eventName: string, callback: (event: any) => boolean | void): () => void // 注册事件
}

Therefore, if we want to change the background color of p, we can do this:

ngAfterViewInit() {
    this.renderer.setStyle(this.demop.nativeElement, &#39;background-color&#39;, &#39;red&#39;); // 通过Renderer2设置p的css样式background-color
}

                                                 


At the end of the article "Angular Development Practice (6): Server-side Rendering", we also mentioned the need for Server-side rendering A few things to keep in mind include not using browser-specific types such as window, document, navigator, and directly manipulating DOM elements.

This brings us to one of Angular’s ​​main features: across all platforms. With the right approach, applications built using Angular can be reused on multiple different platforms - web, mobile web, mobile apps, native apps, and desktop native apps.

In order to support cross-platform, Angular encapsulates the differences of different platforms through abstraction layers. For example, abstract class Renderer2, abstract class RootRenderer, etc. are defined. In addition, the following reference types are defined: ElementRef, TemplateRef, ViewRef, ComponentRef, ViewContainerRef, etc. Obtain DOM elements through template variables, @ViewChild and other methods.

For demonstration, first define a component DemoComponent:

import { AfterViewInit, Component, ElementRef, Renderer2, ViewChild } from &#39;@angular/core&#39;;

@Component({
    template: `
        <p id="demop" #demop>this is p!</p>
        p的id:{{demop.id}} <!-- p的id:demop -->
    `
})
export class DemoComponent implements AfterViewInit {
    @ViewChild(&#39;demop&#39;) demop: ElementRef; // @ViewChild通过模板变量名获取

    constructor(private renderer: Renderer2) {
    }

    ngAfterViewInit() {
        console.log(&#39;p的id:&#39; + this.demop.nativeElement.id); // p的id:demop
        this.renderer.setStyle(this.demop.nativeElement, &#39;background-color&#39;, &#39;red&#39;); // 通过Renderer2设置p的css样式background-color
    }
}

Get the p in the component

In Angular applications, DOM elements should not be obtained directly through native API or jQuery:

let element1 = document.getElementById("demop"); // jQuery获取: $(&#39;#demop&#39;)

Instead, you should get the DOM element through the method provided by Angular:

Template variable

a728b34f8c39ac4b8264402fa7a79be6this is p!94b3e26ee717c64999d7867364b1b4a3
p的id:{{demop.id}} 56a354faacebef689e1d2dd71ed7d1a6

In the component template, we define the template of #demop on p variable, then demop is equal to the DOM object of p, so we can directly obtain the id of p through demop.id.

@ViewChild

@ViewChild('demop') demop: ElementRef; // @ViewChild通过模板变量名获取

ngAfterViewInit() {
    console.log('p的id:' + this.demop.nativeElement.id); // p的id:demop
}

In the component class, we obtain the ElementRef object that wraps the DOM object of p through @ViewChild. The ElementRef is defined as follows:

class ElementRef<T> {
  constructor(nativeElement: T)
  nativeElement: T
}

So we can Get the DOM object of p through this.demop.nativeElement in ngAfterViewInit, and then get the id of the element.

p in the operation component

has obtained the DOM object of p through several methods above, so how do we operate on it (setting styles, attributes, inserting sub-elements, etc.) ? Via raw API or jQuery is definitely not allowed.

In this way, we introduce the Angular abstract class Renderer2 to set styles, attributes, insert sub-elements and other operations on elements.

Renderer2 is defined as follows:

class Renderer2 {
    get data: {...}
    destroyNode: ((node: any) => void) | null
    destroy(): void
    createElement(name: string, namespace?: string | null): any // 创建元素
    createComment(value: string): any // 创建注释元素
    createText(value: string): any // 创建文本元素
    appendChild(parent: any, newChild: any): void // 添加子元素(在最后)
    insertBefore(parent: any, newChild: any, refChild: any): void // 添加子元素(在最前)
    removeChild(parent: any, oldChild: any): void // 移除子元素
    selectRootElement(selectorOrNode: string | any): any // 获取根元素
    parentNode(node: any): any // 获取父元素
    nextSibling(node: any): any // 获取下一个兄弟元素
    setAttribute(el: any, name: string, value: string, namespace?: string | null): void // 设置属性
    removeAttribute(el: any, name: string, namespace?: string | null): void // 移除属性
    addClass(el: any, name: string): void // 添加样式类
    removeClass(el: any, name: string): void // 移除样式类
    setStyle(el: any, style: string, value: any, flags?: RendererStyleFlags2): void // 设置样式
    removeStyle(el: any, style: string, flags?: RendererStyleFlags2): void // 移除样式
    setProperty(el: any, name: string, value: any): void // 设置DOM对象属性,不同于元素属性
    setValue(node: any, value: string): void // 设置元素值
    listen(target: &#39;window&#39; | &#39;document&#39; | &#39;body&#39; | any, eventName: string, callback: (event: any) => boolean | void): () => void // 注册事件
}

Therefore, if we want to change the background color of p, we can do this:

ngAfterViewInit() {
    this.renderer.setStyle(this.demop.nativeElement, &#39;background-color&#39;, &#39;red&#39;); // 通过Renderer2设置p的css样式background-color
}


Related Recommended:

Angular Development Practice (5): In-depth Analysis of Change Monitoring

Angular Development Practice (6): Server-side Rendering

Angular Development Practice (1): Environment Preparation and Framework Construction

The above is the detailed content of Angular development practice (7): Cross-platform operation of DOM and renderer Renderer2. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn