>  기사  >  웹 프론트엔드  >  Angular 개발 사례(7): DOM 및 렌더러 Renderer2의 크로스 플랫폼 작업

Angular 개발 사례(7): DOM 및 렌더러 Renderer2의 크로스 플랫폼 작업

不言
不言원래의
2018-04-02 15:11:414366검색

In "Angular 개발 실습(6): 서버 측 렌더링"이 글의 마지막 부분에서는 서버 측 렌더링에서 기억해야 할 몇 가지 사항도 언급했습니다. window, document, navigator와 같은 브라우저별 유형을 사용하고 DOM 요소를 직접 조작합니다. 服务端渲染中需要牢记的几件事件,其中就包括不要使用windowdocumentnavigator等浏览器特有的类型以及直接操作DOM元素。

这样就引出了 Angular 主要特性之一:横跨所有平台。通过合适的方法,使用 Angular 构建的应用,可复用在多种不同平台的应用上 —— Web、移动 Web、移动应用、原生应用和桌面原生应用。

为了能够支持跨平台,Angular 通过抽象层封装了不同平台的差异。比如定义了抽象类 Renderer2 、抽象类 RootRenderer 等。此外还定义了以下引用类型:ElementRef、TemplateRef、ViewRef 、ComponentRef 和 ViewContainerRef 等。通过 模板变量@ViewChild 等方法获取DOM元素。

为了演示,先定义一个组件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
    }
}

获取组件中的p

在Angular应用中不应该通过原生 API 或者 jQuery 来直接获取DOM元素:

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

而是应该通过Angular提供的方法来获取DOM元素:

模板变量

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

在组件模板中,我们在 p 上定义了 #demop 的模板变量,那么 demop 就等于该 p 的 DOM 对象,因此我们可以通过 demop.id 直接获取 p 的 id。

@ViewChild

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

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

在组件类中,我们通过 @ViewChild 获取到包装有 p 的 DOM 对象的 ElementRef 对象,ElementRef 定义如下:

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

因此我们可以在 ngAfterViewInit 中通过 this.demop.nativeElement 获取到该 p 的 DOM 对象,然后获取元素的id。

操作组件中的p

在上面通过几种方式获取到 p 的 DOM 对象,那么我们要如果对它进行操作呢(设置样式、属性、插入子元素等)?通过原始API 或者 jQuery 肯定是不允许的了。

这样我们就引出Angular抽象类 Renderer2 来对元素进行设置样式、属性、插入子元素等操作。

Renderer2 的定义如下:

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 // 注册事件
}

因此,我们想改变 p 的背景色,就可以这样做:

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

                                               


在《Angular开发实践(六):服务端渲染》这篇文章的最后,我们也提到了在服务端渲染中需要牢记的几件事件,其中就包括不要使用windowdocumentnavigator等浏览器特有的类型以及直接操作DOM元素。

这样就引出了 Angular 主要特性之一:横跨所有平台。通过合适的方法,使用 Angular 构建的应用,可复用在多种不同平台的应用上 —— Web、移动 Web、移动应用、原生应用和桌面原生应用。

为了能够支持跨平台,Angular 通过抽象层封装了不同平台的差异。比如定义了抽象类 Renderer2 、抽象类 RootRenderer 等。此外还定义了以下引用类型:ElementRef、TemplateRef、ViewRef 、ComponentRef 和 ViewContainerRef 等。通过 模板变量@ViewChild 等方法获取DOM元素。

为了演示,先定义一个组件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
    }
}

获取组件中的p

在Angular应用中不应该通过原生 API 或者 jQuery 来直接获取DOM元素:

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

而是应该通过Angular提供的方法来获取DOM元素:

模板变量

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

在组件模板中,我们在 p 上定义了 #demop 的模板变量,那么 demop 就等于该 p 的 DOM 对象,因此我们可以通过 demop.id 直接获取 p 的 id。

@ViewChild

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

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

在组件类中,我们通过 @ViewChild 获取到包装有 p 的 DOM 对象的 ElementRef 对象,ElementRef 定义如下:

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

因此我们可以在 ngAfterViewInit 中通过 this.demop.nativeElement 获取到该 p 的 DOM 对象,然后获取元素的id。

操作组件中的p

在上面通过几种方式获取到 p 的 DOM 对象,那么我们要如果对它进行操作呢(设置样式、属性、插入子元素等)?通过原始API 或者 jQuery 肯定是不允许的了。

这样我们就引出Angular抽象类 Renderer2

이것은 Angular의 주요 기능 중 하나인 크로스 플랫폼을 소개합니다. 올바른 접근 방식을 사용하면 Angular를 사용하여 구축된 애플리케이션을 웹, 모바일 웹, 모바일 앱, 기본 앱, 데스크톱 기본 앱 등 다양한 플랫폼에서 재사용할 수 있습니다.

크로스 플랫폼을 지원하기 위해 Angular는 추상화 계층을 통해 다양한 플랫폼의 차이점을 캡슐화합니다. 예를 들어 추상 클래스 Renderer2, 추상 클래스 RootRenderer 등이 정의되어 있습니다. 또한 ElementRef, TemplateRef, ViewRef, ComponentRef, ViewContainerRef 등의 참조 유형이 정의됩니다. 템플릿 변수@ViewChild와 같은 메서드를 통해 DOM 요소를 가져옵니다.

데모를 위해 먼저 구성 요소를 정의합니다. DemoComponent:

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 // 注册事件
}

구성 요소에 p 가져오기


Angular 애플리케이션에서는 기본 API 또는 jQuery를 통해 DOM 요소를 직접 가져와서는 안 됩니다.
ngAfterViewInit() {
    this.renderer.setStyle(this.demop.nativeElement, &#39;background-color&#39;, &#39;red&#39;); // 通过Renderer2设置p的css样式background-color
}

대신 다음과 같이 해야 합니다. pass DOM 요소를 얻기 위해 Angular에서 제공하는 메소드:

템플릿 변수

rrreee

컴포넌트 템플릿에서 p에 #demop라는 템플릿 변수를 정의한 다음, 데모는 p의 DOM 객체와 같습니다. demop.id를 통해 p의 id를 직접 얻을 수 있습니다.

@ViewChild

rrreee컴포넌트 클래스에서는 @ViewChild를 통해 DOM 객체를 p로 래핑하는 ElementRef 객체를 얻습니다.

rrreee🎜그래서 this.demop를 전달할 수 있습니다. ngAfterViewInit에서 .nativeElement는 p의 DOM 객체를 가져온 다음 요소의 ID를 가져옵니다. 🎜

컴포넌트의 p 작업

🎜 p의 DOM 객체는 위의 여러 방법을 통해 얻어지는데 어떻게 작업합니까(스타일, 속성 설정, 하위 요소 삽입 등)? 원시 API 또는 jQuery를 통한 것은 절대 허용되지 않습니다. 🎜🎜이러한 방식으로 스타일, 속성을 설정하고 하위 요소를 삽입하며 요소에 대한 기타 작업을 수행하는 Angular 추상 클래스 Renderer2를 소개합니다. 🎜🎜Renderer2는 다음과 같이 정의됩니다. 🎜rrreee🎜 따라서 p의 배경색을 변경하려면 다음과 같이 하면 됩니다. 🎜rrreee🎜                                                     🎜

🎜🎜🎜"Angular Development Practice (6): Server-side Rendering" 기사 마지막 부분에서 서버 측 렌더링의 필요성에 대해서도 언급했습니다. > 명심해야 할 몇 가지 사항에는 window, document, navigator와 같은 브라우저별 유형을 사용하지 않고 DOM 요소를 직접 조작하는 것이 포함됩니다. 🎜🎜이것은 Angular의 주요 기능 중 하나인 크로스 플랫폼을 소개합니다. 올바른 접근 방식을 사용하면 Angular를 사용하여 구축된 애플리케이션을 웹, 모바일 웹, 모바일 앱, 기본 앱, 데스크톱 기본 앱 등 다양한 플랫폼에서 재사용할 수 있습니다. 🎜🎜크로스 플랫폼을 지원하기 위해 Angular는 추상화 계층을 통해 다양한 플랫폼의 차이점을 캡슐화합니다. 예를 들어 추상 클래스 Renderer2, 추상 클래스 RootRenderer 등이 정의되어 있습니다. 또한 ElementRef, TemplateRef, ViewRef, ComponentRef, ViewContainerRef 등의 참조 유형이 정의됩니다. 템플릿 변수@ViewChild와 같은 메서드를 통해 DOM 요소를 가져옵니다. 🎜🎜데모를 위해 먼저 구성 요소를 정의합니다. DemoComponent: 🎜rrreee

구성 요소에 p 가져오기

🎜 Angular 애플리케이션에서는 기본 API 또는 jQuery를 통해 DOM 요소를 직접 가져와서는 안 됩니다. 🎜rrreee🎜 대신 다음과 같이 해야 합니다. pass DOM 요소를 얻기 위해 Angular에서 제공하는 메소드: 🎜

템플릿 변수

rrreee🎜컴포넌트 템플릿에서 p에 #demop라는 템플릿 변수를 정의한 다음, 데모는 p의 DOM 객체와 같습니다. demop.id를 통해 p의 id를 직접 얻을 수 있습니다. 🎜

@ViewChild

rrreee🎜컴포넌트 클래스에서는 @ViewChild를 통해 DOM 객체를 p로 래핑하는 ElementRef 객체를 얻습니다. 🎜rrreee🎜그래서 this.demop를 전달할 수 있습니다. ngAfterViewInit에서 .nativeElement는 p의 DOM 객체를 가져온 다음 요소의 ID를 가져옵니다. 🎜

컴포넌트의 p 작업

🎜 p의 DOM 객체는 위의 여러 방법을 통해 얻어지는데 어떻게 작업합니까(스타일, 속성 설정, 하위 요소 삽입 등)? 원시 API 또는 jQuery를 통한 것은 절대 허용되지 않습니다. 🎜🎜이러한 방식으로 스타일, 속성을 설정하고 하위 요소를 삽입하며 요소에 대한 기타 작업을 수행하는 Angular 추상 클래스 Renderer2를 소개합니다. 🎜🎜Renderer2는 다음과 같이 정의됩니다. 🎜rrreee🎜 따라서 p의 배경색을 변경하려면 다음과 같이 하면 됩니다. 🎜rrreee🎜🎜🎜🎜관련 권장 사항: 🎜🎜🎜Angular 개발 실습(5): In- 변화 모니터링에 대한 심층 분석🎜🎜

Angular 개발 실습(6): 서버 측 렌더링

Angular 개발 실습(1): 환경 준비 및 프레임워크 구축

위 내용은 Angular 개발 사례(7): DOM 및 렌더러 Renderer2의 크로스 플랫폼 작업의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.