首頁  >  文章  >  web前端  >  在Angular4中如何使用ElementRef應用

在Angular4中如何使用ElementRef應用

亚连
亚连原創
2018-06-04 14:22:571330瀏覽

本篇文章主要介紹了Angular4 ElementRef的應用,現在分享給大家,也給大家做個參考。

Angular 的口號是- "一套框架,多種平台。同時適用手機與桌面(One framework.Mobile & desktop.)",即​​Angular 是支援開發跨平台的應用,例如:Web 應用、行動Web 應用程式、原生行動應用程式和原生桌面應用程式等。

為了能夠支援跨平台,Angular 透過抽象層封裝了不同平台的差異,統一了 API 介面。如定義了抽象類別 Renderer 、抽象類別 RootRenderer 等。另外也定義了以下參考類型:ElementRef、TemplateRef、ViewRef 、ComponentRef 和 ViewContainerRef 等。下面我們就來分析ElementRef 類別:

ElementRef的作用

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

ElementRef的定義

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

#ElementRef的應用程式

我們先來介紹整體需求,我們想要在頁面成功渲染後,取得頁面中的p 元素,並改變該p 元素的背景顏色。接下來我們來一步步,實現這個需求。

首先我們要先取得 p 元素,在文中 "ElementRef 的作用" 部分,我們已經提到可以利用 Angular 提供的強大的依賴注入特性,取得封裝後的 native 元素。在瀏覽器中 native 元素就是 DOM 元素,我們只要先取得 my-app元素,然後利用 querySelector API 就能取得頁面中 p 元素。具體程式碼如下:

import { Component, ElementRef } from '@angular/core'; @Component({
 selector: 'my-app',
 template: `
  <h1>Welcome to Angular World</h1>
  <p>Hello {{ name }}</p>
 `,
}) export class AppComponent {

 name: string = &#39;Semlinker&#39;; constructor(private elementRef: ElementRef) { let pEle = this.elementRef.nativeElement.querySelector(&#39;p&#39;); console.dir(pEle);
 }
}

執行上面程式碼,在控制台中沒有出現異常,但是輸出的結果卻是 null 。什麼情況 ?沒有拋出異常,我們可以推斷 this.elementRef.nativeElement 這個物件是存在,但卻找不到它的子元素,那應該是在呼叫建構函式的時候,my-app 元素下的子元素還未建立。那要怎麼解決這個問題呢 ?沉思中… ,不是有 setTimeout 麼,我們在稍微改造一下:

 constructor(private elementRef: ElementRef) {
 setTimeout(() => { // 此处需要使用箭头函数哈,你懂的...
   let pEle = this.elementRef.nativeElement.querySelector(&#39;p&#39;);
   console.dir(pEle);
  }, 0); }

問題解決了,但感覺不是很優雅 ?有沒有更好的方案,答案是肯定的。 Angular 不是有提供元件生命週期的鉤子,我們可以選擇一個合適的時機,然後取得我們想要的 p 元素。

 import { Component, ElementRef, AfterViewInit } from &#39;@angular/core&#39;; @Component({
 selector: &#39;my-app&#39;,
 template: `
  <h1>Welcome to Angular World</h1>
  <p>Hello {{ name }}</p>
 `,
}) export class AppComponent {
 name: string = &#39;Semlinker&#39;; // 在构造函数中 this.elementRef = elementRef 是可选的,编译时会自动赋值 // function AppComponent(elementRef) { this.elementRef = elementRef; } constructor(private elementRef: ElementRef) { } 
 ngAfterViewInit() { // 模板中的元素已创建完成 console.dir(this.elementRef.nativeElement.querySelector(&#39;p&#39;)); // let greetp: HTMLElement = this.elementRef.nativeElement.querySelector(&#39;p&#39;); // greetp.style.backgroundColor = &#39;red&#39;; }
}

運行一下上面的程式碼,我們看到了意料中的 p 元素。我們直接選用 ngAfterViewInit 這個鉤子,不要問我為什麼,因為它看得最順眼咯。不過我們後面也會有專門的文章,詳細分析 Angular 組件的生命週期。成功取到 p 元素,就剩下的事情就好辦了,直接透過 style 物件設定元素的背景顏色。

功能雖然已經實現了,但還有優化的空間麼?

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

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

 @ViewChild(&#39;greet&#39;)
 greetp: ElementRef;

 ngAfterViewInit() { this.greetp.nativeElement.style.backgroundColor = &#39;red&#39;;
 }
}

是不是感覺瞬間高大上了,不過先等等,上面的程式碼是不是還有進一步的最佳化空間呢 ?我們看到設定 p 元素的背景,我們是預設應用的運行環境在是瀏覽器中。前面已經介紹了,我們要盡量減少應用層與渲染層之間強耦合關係,讓我們應用能夠靈活地運行在不同環境中。最後我們來看一下,最終優化後的程式碼:

import { Component, ElementRef, ViewChild, AfterViewInit, Renderer } from &#39;@angular/core&#39;; @Component({
 selector: &#39;my-app&#39;,
 template: `
  <h1>Welcome to Angular World</h1>
  <p #greet>Hello {{ name }}</p>
 `,
}) export class AppComponent {
 name: string = &#39;Semlinker&#39;; @ViewChild(&#39;greet&#39;)
 greetp: ElementRef; constructor(private elementRef: ElementRef, private renderer: Renderer) { }

 ngAfterViewInit() { // this.greetp.nativeElement.style.backgroundColor = &#39;red&#39;; this.renderer.setElementStyle(this.greetp.nativeElement, &#39;backgroundColor&#39;, &#39;red&#39;);
 }
}

1.Renderer API 還有哪些常用的方法 ?

export abstract class Renderer { // 创建元素 abstract createElement(parentElement: any, name: string, 
   debugInfo?: RenderDebugInfo): any; // 创建文本元素 abstract createText(parentElement: any, value: string, 
   debugInfo?: RenderDebugInfo): any; // 设置文本 abstract setText(renderNode: any, text: string): void; // 设置元素Property abstract setElementProperty(renderElement: any, propertyName: string, 
   propertyValue: any): void; // 设置元素Attribute abstract setElementAttribute(renderElement: any, attributeName: string, 
   attributeValue: string): void; // 设置元素的Class abstract setElementClass(renderElement: any, className: string,
   isAdd: boolean): void; // 设置元素的样式 abstract setElementStyle(renderElement: any, styleName: string, 
   styleValue: string): void;  
}

要注意的是在 Angular 4.x 版本,我們使用 Renderer2 取代 Renderer (Angular V2)。

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

export abstract class Renderer2 { abstract createElement(name: string, namespace?: string|null): any; abstract createComment(value: string): any; abstract createText(value: string): 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: &#39;window&#39;|&#39;document&#39;|&#39;body&#39;|any, eventName: string,
   callback: (event: any) => boolean | void): () => void;
}

上面是我整理給大家的,希望今後會對大家有幫助。

相關文章:

有關在Vue中點擊元件外關閉元件方法(詳細教學)

關於在使用vue.js標籤屬性中插入變數參數的方法(詳細教學)

#使用Vue的路由權限管理方面的問題(詳細教學)

以上是在Angular4中如何使用ElementRef應用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn