この記事では主に Angular4 ElementRef のアプリケーションを紹介します。
Angular のスローガンは、「1 つのフレームワーク、複数のプラットフォーム。携帯電話とデスクトップの両方に適しています (1 つのフレームワーク。モバイルとデスクトップ。)」です。つまり、Angular は、次のようなクロスプラットフォーム アプリケーションの開発をサポートしています。Web アプリケーション、モバイル Web アプリケーション、ネイティブ モバイル アプリケーション、ネイティブ デスクトップ アプリケーションなど。
クロスプラットフォームをサポートするために、Angular は抽象化レイヤーを通じてさまざまなプラットフォームの違いをカプセル化し、API インターフェイスを統合します。例えば、抽象クラスRenderer、抽象クラスRootRendererなどが定義されている。さらに、ElementRef、TemplateRef、ViewRef、ComponentRef、ViewContainerRef などの参照タイプが定義されています。以下の ElementRef クラスを分析してみましょう:
アプリケーション層で DOM を直接操作すると、アプリケーション層とレンダリング層の間に強い結合が生じ、その結果、アプリケーションは異なる環境で実行できなくなります。 , Web ワーカーなどでは、Web ワーカー環境では DOM を直接操作できないためです。興味のある読者は、Web Workers でサポートされているクラスとメソッドを読むことができます。 ElementRef を使用すると、さまざまなプラットフォームのビュー レイヤにネイティブ要素をカプセル化できます (ブラウザ環境では、ネイティブ要素は通常 DOM 要素を参照します)。最後に、Angular が提供する強力な依存関係注入機能を利用して、ネイティブ要素に簡単にアクセスできます。要素。
export class ElementRef { public nativeElement: any; constructor(nativeElement: any) { this.nativeElement = nativeElement; } }
まず全体的な要件を紹介し、ページ内のp要素を取得し、ページが正常に作成された後にp要素の背景色を変更します。レンダリングされます。次に、この要件を段階的に実装していきます。
まず、p 要素を取得する必要があります。この記事の「ElementRef の役割」セクションで、Angular が提供する強力な依存関係注入機能を使用して、カプセル化されたネイティブ要素を取得できると述べました。ブラウザーでは、ネイティブ要素は 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 = 'Semlinker'; constructor(private elementRef: ElementRef) { let pEle = this.elementRef.nativeElement.querySelector('p'); console.dir(pEle); } }
上記のコードを実行すると、コンソールで例外は発生しませんが、出力結果は null になります。どういう状況ですか? 例外はスローされません。オブジェクト this.elementRef.nativeElement が存在することは推測できますが、その子要素が見つからないのは、コンストラクターが呼び出されたときに my-app 要素の下にある子要素がまだ作成されていないためです。では、この問題をどうやって解決すればいいのでしょうか?考え中... setTimeout はありませんか? 少し改修中です:
constructor(private elementRef: ElementRef) { setTimeout(() => { // 此处需要使用箭头函数哈,你懂的... let pEle = this.elementRef.nativeElement.querySelector('p'); console.dir(pEle); }, 0); }
問題は解決されましたが、あまりエレガントではありませんか?もっと良い解決策はあるでしょうか? 答えは「はい」です。 Angular はコンポーネントのライフサイクルに対するフックを提供しません。適切な時間を選択して、必要な p 要素を取得できます。
import { Component, ElementRef, AfterViewInit } from '@angular/core'; @Component({ selector: 'my-app', template: ` <h1>Welcome to Angular World</h1> <p>Hello {{ name }}</p> `, }) export class AppComponent { name: string = 'Semlinker'; // 在构造函数中 this.elementRef = elementRef 是可选的,编译时会自动赋值 // function AppComponent(elementRef) { this.elementRef = elementRef; } constructor(private elementRef: ElementRef) { } ngAfterViewInit() { // 模板中的元素已创建完成 console.dir(this.elementRef.nativeElement.querySelector('p')); // let greetp: HTMLElement = this.elementRef.nativeElement.querySelector('p'); // greetp.style.backgroundColor = 'red'; } }
上記のコードを実行すると、予想される p 要素が表示されます。 ngAfterViewInit フックを直接使用しています。理由は聞かないでください。それが最も目に心地よいからです。ただし、後で Angular コンポーネントのライフサイクルを詳細に分析する特別な記事も作成する予定です。 p 要素を取得できたら、あとはスタイル オブジェクトを介して要素の背景色を直接設定するのは簡単です。
機能は実装されましたが、まだ最適化の余地はありますか?
import { Component, ElementRef, ViewChild, AfterViewInit } from '@angular/core'; @Component({ selector: 'my-app', template: ` <h1>Welcome to Angular World</h1> <p #greet>Hello {{ name }}</p> `, }) export class AppComponent { name: string = 'Semlinker'; @ViewChild('greet') greetp: ElementRef; ngAfterViewInit() { this.greetp.nativeElement.style.backgroundColor = 'red'; } }
すぐに背が高くなったように感じますか? しかし、上記のコードをさらに最適化する余地はありますか? p 要素の背景が設定されており、ブラウザーでのデフォルトのアプリケーション実行環境であることがわかります。前述したように、アプリケーションがさまざまな環境で柔軟に実行できるように、アプリケーション層とレンダリング層の間の強い結合関係を最小限に抑える必要があります。最後に、最終的に最適化されたコードを見てみましょう:
import { Component, ElementRef, ViewChild, AfterViewInit, Renderer } from '@angular/core'; @Component({ selector: 'my-app', template: ` <h1>Welcome to Angular World</h1> <p #greet>Hello {{ name }}</p> `, }) export class AppComponent { name: string = 'Semlinker'; @ViewChild('greet') greetp: ElementRef; constructor(private elementRef: ElementRef, private renderer: Renderer) { } ngAfterViewInit() { // this.greetp.nativeElement.style.backgroundColor = 'red'; this.renderer.setElementStyle(this.greetp.nativeElement, 'backgroundColor', 'red'); } }
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 以降のバージョンでは、Renderer (Angular V2) の代わりに Renderer2 を使用することに注意してください。
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: 'window'|'document'|'body'|any, eventName: string, callback: (event: any) => boolean | void): () => void; }
以上、皆様のお役に立てれば幸いです。
関連記事:
Vueでコンポーネントの外側をクリックしてコンポーネントを閉じる方法について(詳細チュートリアル)
vue.jsのタグ属性に変数パラメータを挿入する方法について(詳細チュートリアル)
Vue を使用したルーティング許可管理の問題 (詳細なチュートリアル)
以上がAngular4でElementRefアプリケーションを使用する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。