99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

ElementRef簡介

2018-08-28 10:27 更新

查看新版Angular ElementRef 簡介

Angular 的口號是:

一套框架,多種平臺。同時適用手機與桌面(One framework.Mobile & desktop.)

即 Angular 是支持開發(fā)跨平臺的應用,比如:Web應用、移動Web應用、原生移動應用和原生桌面應用等。

為了能夠支持跨平臺,Angular 通過抽象層封裝了不同平臺的差異,統(tǒng)一了 API 接口。如定義了抽象類 Renderer2、抽象類 RendererFactory2 等。此外還定義了以下抽象類:

  • ElementRef
  • TemplateRef
  • ViewRef
  • ComponentRef
  • ViewContainerRef

接下來我們正式來介紹本文的主角 - ElementRef

ElementRef

ElementRef 的作用

在應用層直接操作 DOM,就會造成應用層與渲染層之間強耦合,導致我們的應用無法運行在不同環(huán)境,如 web worker 中,因為在 Web Worker 環(huán)境中,是不能直接操作 DOM。有興趣的讀者,可以閱讀一下 Web Workers 中支持的類和方法 這篇文章。通過 ElementRef 我們就可以封裝不同平臺下視圖層中的 native 元素 (在瀏覽器環(huán)境中,native 元素通常是指 DOM 元素),最后借助于 Angular 提供的強大的依賴注入特性,我們就可以輕松地訪問到 native 元素。

ElementRef 的定義

export class ElementRef {
  public nativeElement: any;
  constructor(nativeElement: any) { this.nativeElement = nativeElement; }
}

ElementRef 的應用

我們先來介紹一下整體需求,我們想在頁面成功渲染后,獲取頁面中的 div 元素,并改變該 div 元素的背景顏色。接下來我們來一步步,實現(xiàn)這個需求。

首先我們要先獲取 div 元素,在文中 "ElementRef 的作用" 部分,我們已經(jīng)提到可以利用 Angular 提供的強大的依賴注入特性,獲取封裝后的 native 元素。在瀏覽器中 native 元素就是 DOM 元素,我們只要先獲取 myapp元素,然后利用 querySelector API 就能獲取頁面中 div元素。具體代碼如下:

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


@Component({
  selector: 'my-app',
  template: `
    <h1>Welcome to Angular World</h1>
    <div>Hello {{ name }}</div>
  `,
})
export class AppComponent {


  name: string = 'Semlinker';


  constructor(private elementRef: ElementRef) {
    let divEle = this.elementRef.nativeElement.querySelector('div');
    console.dir(divEle);
  }
}

運行上面代碼,在控制臺中沒有出現(xiàn)異常,但是輸出的結(jié)果卻是 null 。什么情況 ? 沒有拋出異常,我們可以推斷 this.elementRef.nativeElement 這個對象是存在,但卻找不到它的子元素,那應該是在調(diào)用構(gòu)造函數(shù)的時候,my-app 元素下的子元素還未創(chuàng)建。那怎么解決這個問題呢 ?沉思中… ,不是有 setTimeout 么,我們在稍微改造一下:

constructor(private elementRef: ElementRef) {
  setTimeout(() => { // 此處需要使用箭頭函數(shù)哈,你懂的...
      let divEle = this.elementRef.nativeElement.querySelector('div');
      console.dir(divEle);
   }, 0);
}

更新一下代碼,此時控制臺成功輸出了 div 。為什么添加個 setTimeout 就能成功獲取到想要的 div 元素呢?此處就不展開了,有興趣的讀者可以參考 - What the heck is the event loop anyway? 這個演講的示例。

問題解決了,但感覺不是很優(yōu)雅 ?有沒有更好的方案,答案是肯定的。Angular 不是有提供組件生命周期的鉤子,我們可以選擇一個合適的時機,然后獲取我們想要的 div 元素。

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


@Component({
  selector: 'my-app',
  template: `
    <h1>Welcome to Angular World</h1>
    <div>Hello {{ name }}</div>
  `,
})
export class AppComponent {


  name: string = 'Semlinker';


  // 在構(gòu)造函數(shù)中 this.elementRef = elementRef 是可選的,編譯時會自動賦值
  // function AppComponent(elementRef) { this.elementRef = elementRef; }
  constructor(private elementRef: ElementRef) { } 


  ngAfterViewInit() { // 模板中的元素已創(chuàng)建完成
    console.dir(this.elementRef.nativeElement.querySelector('div'));
    // let greetDiv: HTMLElement = this.elementRef.nativeElement.querySelector('div'); 
    // greetDiv.style.backgroundColor = 'red';
  }
}

運行一下上面的代碼,我們看到了意料中的 div 元素。我們直接選用 ngAfterViewInit 這個鉤子,不要問我為什么,因為它看得最順眼咯。不過我們后面也會有專門的文章,詳細分析一下 Angular 2 組件的生命周期。成功取到 div 元素,就剩下的事情就好辦了,直接通過 style 對象設置元素的背景顏色。

功能雖然已經(jīng)實現(xiàn)了,但還有優(yōu)化的空間么?在 Angular 2 Decorators part - 2 文章中我們有談到 Angular 內(nèi)置的屬性裝飾器,如 @ContentChild、 @ContentChildren、@ViewChild、@ViewChildren 等。相信讀者看完后,已經(jīng)猜到我們的優(yōu)化方案了。具體示例如下:

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


@Component({
  selector: 'my-app',
  template: `
    <h1>Welcome to Angular World</h1>
    <div #greet>Hello {{ name }}</div>
  `,
})
export class AppComponent {
  name: string = 'Semlinker';


  @ViewChild('greet')
  greetDiv: ElementRef;


  ngAfterViewInit() {
    this.greetDiv.nativeElement.style.backgroundColor  = 'red';
  }
}

是不是感覺瞬間高大上了,不過先等等,上面的代碼是不是還有進一步的優(yōu)化空間呢 ?我們看到設置 div 元素的背景,我們是默認應用的運行環(huán)境在是瀏覽器中。前面已經(jīng)介紹了,我們要盡量減少應用層與渲染層之間強耦合關系,從而讓我們應用能夠靈活地運行在不同環(huán)境。最后我們來看一下,最終優(yōu)化后的代碼:

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


@Component({
  selector: 'app-root',
  template: `
    <h1>Welcome to Angular World</h1>
    <div #greet>Hello {{ name }}</div>
  `,
})
export class AppComponent {
  name: string = 'Semlinker';


  @ViewChild('greet')
  greetDiv: ElementRef;


  constructor(private elementRef: ElementRef, private renderer: Renderer2) { }


  ngAfterViewInit() {
    this.renderer.setStyle(this.greetDiv.nativeElement, 'backgroundColor', 'red');
  }
}

最后我們通過 renderer 對象提供的 API 優(yōu)雅地設置了 div 元素的背景顏色。

我有話說

Renderer2 API 還有哪些常用的方法 ?

// packages/core/src/render/api.ts
export abstract class Renderer2 {
  // 創(chuàng)建元素
  abstract createElement(name: string, namespace?: string|null): any;

  
  // 創(chuàng)建文本元素
  abstract createText(value: string): any;

    
  // 創(chuàng)建Comment元素
  abstract createComment(value: string): any;

    
  // 設置元素Property屬性
  abstract setProperty(el: any, name: string, value: any): void;

    
  // 設置元素Attribute屬性
  abstract setAttribute(el: any, name: string, value: string, 
    namespace?: string|null): void;

    
  // 設置元素Class類
  abstract addClass(el: any, name: string): void;   

    
  // 設置元素的樣式
  abstract setStyle(el: any, style: string, value: any, 
    flags?: RendererStyleFlags2): void;
}
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號