国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Angular Elements 及其運(yùn)作原理

qingshanli1988 / 1389人閱讀

摘要:以下是關(guān)于中一些模塊的概要以及它們與這篇文章的關(guān)聯(lián)性這個(gè)模塊實(shí)現(xiàn)了我們在這篇文章中討論的關(guān)于的幾個(gè)回調(diào)函數(shù),同時(shí)它還會初始化一個(gè)策略類,這個(gè)類會作為連接和的橋梁。

現(xiàn)在,Angular Elements 這個(gè)項(xiàng)目已經(jīng)在社區(qū)引起一定程度的討論。這是顯而易見的,因?yàn)?Angular Elements 提供了很多開箱即用的、十分強(qiáng)大的功能:

通過使用原生的 HTML 語法來使用 Angular Elements —— 這意味著不再需要了解 Angular 的相關(guān)知識

它是自啟動的,并且一切都可以按預(yù)期那樣運(yùn)作

它符合 Web Components 規(guī)范,這意味著它可以在任何地方使用

雖然你沒有使用 Angular 開發(fā)整個(gè)網(wǎng)站,但你仍然可以從 Angular Framework 這個(gè)龐大的體系中收益

@angular/elements這個(gè)包提供可將 Angular 組件轉(zhuǎn)化為原生 Web Components 的功能,它基于瀏覽器的 Custom Elements API 實(shí)現(xiàn)。Angular Elements 提供一種更簡潔、對開發(fā)者更友善、更快樂地開發(fā)動態(tài)組件的方式 —— 在幕后它基于同樣的機(jī)制(指創(chuàng)建動態(tài)組件),但隱藏了許多樣板代碼。

關(guān)于如何通過 @angular/elements 創(chuàng)建一個(gè) Custom Element,已經(jīng)有大量的文章進(jìn)行闡述,所以在這篇文章將深入一點(diǎn),對它在 Angular 中的具體工作原理進(jìn)行剖析。這也是我們開始研究 Angular Elements 的一系列文章的原因,我們將在其中詳細(xì)解釋 Angular 如何在 Angular Elements 的幫助下實(shí)現(xiàn) Custom Elements API。

Custom Elements(自定義元素)

要了解更多關(guān)于 Custom Elements 的知識,可以通過 developers.google 中的這篇文章進(jìn)行學(xué)習(xí),文章詳細(xì)介紹了與 Custom Elements API 相關(guān)的內(nèi)容。

這里針對 Custom Elements,我們使用一句話來概括:

使用 Custom Elements,web 開發(fā)者可以創(chuàng)建一個(gè)新的 HTML 標(biāo)簽、增加已有的 HTML 標(biāo)簽以及繼承其他開發(fā)者所開發(fā)的組件。
原生 Custom Elements

讓我們來看看下面的例子,我們想要創(chuàng)建一個(gè)擁有 name 屬性的 app-hello HTML 標(biāo)簽。可以通過 Custom Elements API 來完成這件事。在文章的后續(xù)章節(jié),我們將演示如何使用 Angular 組件的 @Input 裝飾器與 這個(gè) name 屬性保持同步。但是現(xiàn)在,我們不需要使用 Angular Elements 或者 ShadowDom 或者使用任何關(guān)于 Angular 的東西來創(chuàng)建一個(gè) Custom Element,我們僅使用原生的 Custom Components API。

首先,這是我們的 HTML 標(biāo)記:

要實(shí)現(xiàn)一個(gè) Custom Element,我們需要分別實(shí)現(xiàn)如下在標(biāo)準(zhǔn)中定義的 hooks:

callback summary
constructor 如果需要的話,可在其中初始化 state 或者 shadowRoot,在這篇文章中,我們不需要
connectedCallback 在元素被添加到 DOM 中時(shí)會被調(diào)用,我們將在這個(gè) hook 中初始化我們的 DOM 結(jié)構(gòu)和事件監(jiān)聽器
disconnectedCallback 在元素從 DOM 中被移除時(shí)被調(diào)用,我們將在這個(gè) hook 中清除我們的 DOM 結(jié)構(gòu)和事件監(jiān)聽器
attributeChangedCallback 在元素屬性變化時(shí)被調(diào)用,我們將在這個(gè) hook 中更新我們內(nèi)部的 dom 元素或者基于屬性改變后的狀態(tài)

如下是我們關(guān)于 Hello Custom Element 的實(shí)現(xiàn)代碼:

class AppHello extends HTMLElement {
  constructor() {
    super();
  }
  // 這里定義了那些需要被觀察的屬性,當(dāng)這些屬性改變時(shí),attributeChangedCallback 這個(gè) hook 會被觸發(fā)
  static get observedAttributes() {return ["name"]; }

  // getter to do a attribute -> property reflection
  get name() {
    return this.getAttribute("name");
  }

  // setter to do a property -> attribute reflection
  // 通過 setter 來完成類屬性到元素屬性的映射操作
  set name(val) {
    this.setAttribute("name", val);
  }

  connectedCallback() {
    this.div = document.createElement("div");
    this.text = document.createTextNode(this.name || "");
    this.div.appendChild(this.text);
    this.appendChild(this.div);
  }

  disconnectedCallback() {
    this.removeChild(this.div);
  }

  attributeChangedCallback(attrName, oldVal, newVal) {
    if (attrName === "name" && this.text) {
      this.text.textContent = newVal;
    }
  }
}

customElements.define("hello-elem", AppHello);

這里是可運(yùn)行實(shí)例的鏈接。這樣我們就實(shí)現(xiàn)了第一版的 Custom Element,回顧一下,這個(gè) app-hellp 標(biāo)簽包含一個(gè)文本節(jié)點(diǎn),并且這個(gè)節(jié)點(diǎn)將會渲染通過 app-hello 標(biāo)簽 name 屬性傳遞進(jìn)來的任何內(nèi)容,這一切僅僅基于原生 javascript。

將 Angular 組件導(dǎo)出為 Custom Element

既然我們已經(jīng)了解了關(guān)于實(shí)現(xiàn)一個(gè) HTML Custom Element 所涉及的內(nèi)容,讓我們來使用 Angular實(shí)現(xiàn)一個(gè)相同功能的組件,之后再使它成為一個(gè)可用的 Custom Element。

首先,讓我們從一個(gè)簡單的 Angular 組件開始:

import { Component, Input } from "@angular/core";

@Component({
  selector: "app-hello",
  template: `
{{name}}
` }) export class HelloComponent { @Input() name: string; }

正如你所見,它和上面的例子在功能上一模一樣。

現(xiàn)在,要將這個(gè)組件包裝為一個(gè) Custom Element,我們需要創(chuàng)建一個(gè) wrapper class 并實(shí)現(xiàn)所有 Custom Elements 中定義的 hooks:

class HelloComponentClass extends HTMLElement {
  constructor() {
    super();
  }

  static get observedAttributes() {
  }

  connectedCallback() {
  }

  disconnectedCallback() {
  }

  attributeChangedCallback(attrName, oldVal, newVal) {
  }
}

下一步,我們要做的是橋接 HelloComponentHelloComponentClass。它們之間的橋會將 Angular Component 和 Custom Element 連接起來,如圖所示:

要完成這座橋,讓我們來依次實(shí)現(xiàn) Custom Elements API 中所要求的每個(gè)方法,并在這個(gè)方法中編寫關(guān)于綁定 Angular 的代碼:

callback summary angular part
constructor 初始化內(nèi)部狀態(tài) 進(jìn)行一些準(zhǔn)備工作
connectedCallback 初始化視圖、事件監(jiān)聽器 加載 Angular 組件
disconnectedCallback 清除視圖、事件監(jiān)聽器 注銷 Angular 組件
attributeChangedCallback 處理屬性變化 處理 @Input 變化
1. constructor()

我們需要在 connectedCallback() 方法中初始化 HelloComponent,但是在這之前,我們需要在 constructor 方法中進(jìn)行一些準(zhǔn)備工作。

順便,關(guān)于如何動態(tài)構(gòu)造 Angular 組件可以通過閱讀Dynamic Components in Angular這篇文章進(jìn)行了解。它其中闡述的運(yùn)作機(jī)制和我們這里使用的一模一樣。

所以,要讓我們的 Angular 動態(tài)組件能夠正常工作(需要 componentFactory 能夠被編譯),我們需要將 HelloComponent 添加到 NgModuleentryComponents 屬性(它是一個(gè)列表)中去:

@NgModule({
  imports: [
    BrowserModule
  ],
  declarations: [HelloComponent],
  entryComponents: [HelloComponent]
})
export class CustomElementsModule {
  ngDoBootstrap() {}
}

基本上,調(diào)用 prepare() 方法會完成兩件事:

它會基于組件的定義初始化一個(gè) factoryComponent 工廠方法

它會基于 Angular 組件的 inputs 初始化 observedAttributes,以便我們在 attributeChangedCallback() 中完成我們需要做的事

class AngularCustomElementBridge {
  prepare(injector, component) {
    this.componentFactory = injector.get(ComponentFactoryResolver).resolveComponentFactory(component);

    // 我們使用 templateName 來處理 @Input("aliasName") 這種情形
    this.observedAttributes = componentFactory.inputs.map(input => input.templateName); 
  }
}
2. connectedCallback()

在這個(gè)回調(diào)函數(shù)中,我們將看到:

初始化我們的 Angular 組件(就如創(chuàng)建動態(tài)組件那樣)

設(shè)置組件的初始 input 值

在渲染組件時(shí),觸發(fā)臟檢查機(jī)制

最后,將 HostView 增加到 ApplicationRef

如下是實(shí)戰(zhàn)代碼:

class AngularCustomElementBridge {
  initComponent(element: HTMLElement) {
    // 首先我們需要 componentInjector 來初始化組件
    // 這里的 injector 是 Custom Element 外部的注入器實(shí)例,調(diào)用者可以在這個(gè)實(shí)例中注冊
    // 他們自己的 providers
    const componentInjector = Injector.create([], this.injector);
  
    this.componentRef = this.componentFactory.create(componentInjector, null, element);

    // 然后我們要檢查是否需要初始化組件的 input 的值
    // 在本例中,在 Angular Element 被加載之前,user 可能已經(jīng)設(shè)置了元素的屬性
    // 這些值被保存在 initialInputValues 這個(gè) map 結(jié)構(gòu)中
    this.componentFactory.inputs.forEach(prop => this.componentRef.instance[prop.propName] = this.initialInputValues[prop.propName]);

    // 之后我們會觸發(fā)臟檢查,這樣組件在事件循環(huán)的下一個(gè)周期會被渲染
    this.changeDetectorRef.detectChanges();
    this.applicationRef = this.injector.get(ApplicationRef);

    // 最后,我們使用 attachView 方法將組件的 HostView 添加到 applicationRef 中
    this.applicationRef.attachView(this.componentRef.hostView);
  }
}
3. disconnectedCallback()

這個(gè)十分容易,我們僅需要在其中注銷 componentRef 即可:

class AngularCustomElementBridge {
  destroy() {
    this.componentRef.destroy();
  }
}
4. attributeChangedCallback()

當(dāng)元素屬性發(fā)生改變時(shí),我們需要相應(yīng)地更新 Angular 組件并觸發(fā)臟檢查:

class AngularCustomElementBridge {
  setInputValue(propName, value) {
    if (!this.componentRef) {
      this.initialInputValues[propName] = value;
      return;
    }
    if (this.componentRef[propName] === value) {
      return;
    }
    this.componentRef[propName] = value;
    this.changeDetectorRef.detectChanges();
  }
}
5. Finally, we register the Custom Element
customElements.define("hello-elem", HelloComponentClass);

這是一個(gè)可運(yùn)行的例子鏈接。

總結(jié)

這就是根本思想。通過在 Angular 中使用動態(tài)組件,我們簡單實(shí)現(xiàn)了 Angular Elements 所提供的基礎(chǔ)功能,重要的是,沒有使用 @angular/element 這個(gè)庫。

當(dāng)然,不要誤解 —— Angular Elements 的功能十分強(qiáng)大。文章中所涉及的所有實(shí)現(xiàn)邏輯在 Angular Elements 都已被抽象化,使用這個(gè)庫可以使我們的代碼更優(yōu)雅,可讀性和維護(hù)性也更好,同時(shí)也更易于擴(kuò)展。

以下是關(guān)于 Angular Elements 中一些模塊的概要以及它們與這篇文章的關(guān)聯(lián)性:

create-custom-element.ts:這個(gè)模塊實(shí)現(xiàn)了我們在這篇文章中討論的關(guān)于 Custom Element 的幾個(gè)回調(diào)函數(shù),同時(shí)它還會初始化一個(gè) NgElementStrategy 策略類,這個(gè)類會作為連接 Angular Component 和 Custom Elements 的橋梁。當(dāng)前,我們僅有一個(gè)策略 —— component-factory-strategy.ts —— 它的運(yùn)作機(jī)制與本文例子中演示的大同小異。在將來,我們可能會有其他策略,并且我們還可以實(shí)現(xiàn)自定義策略。

component-factory-strategy.ts:這個(gè)模塊使用一個(gè) component 工廠函數(shù)來創(chuàng)建和銷毀組件引用。同時(shí)它還會在 input 改變時(shí)觸發(fā)臟檢查。這個(gè)運(yùn)作過程在上文的例子中也有被提及。

下次我們將闡述 Angular Elements 通過 Custom Events 輸出事件。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/96167.html

相關(guān)文章

  • 【教學(xué)向】150行代碼教你實(shí)現(xiàn)一個(gè)低配版的MVVM庫(2)- 代碼篇

    摘要:也放出地址,上面有完整工程以及在線演示地址相關(guān)閱讀教學(xué)向行代碼教你實(shí)現(xiàn)一個(gè)低配版的庫原理篇教學(xué)向行代碼教你實(shí)現(xiàn)一個(gè)低配版的庫代碼篇教學(xué)向再加行代碼教你實(shí)現(xiàn)一個(gè)低配版的庫設(shè)計(jì)篇教學(xué)向再加行代碼教你實(shí)現(xiàn)一個(gè)低配版的庫原理篇 書接上一篇: 150行代碼教你實(shí)現(xiàn)一個(gè)低配版的MVVM庫(1)- 原理篇 寫在前面 為了便于分模塊,和閱讀,我使用了Typescript來進(jìn)行coding,總行數(shù)是正好...

    loonggg 評論0 收藏0
  • “別更新了,學(xué)不動了” 之:全棧開發(fā)者 2019 應(yīng)該學(xué)些什么?

    摘要:但是,有一件事是肯定的年對全棧開發(fā)者的需求量很大。有一些方法可以解決這個(gè)問題,例如模式,或者你可以這么想,其實(shí)谷歌機(jī)器人在抓取單頁應(yīng)用程序時(shí)沒有那么糟糕。谷歌正在這方面努力推進(jìn),但不要指望在年會看到任何突破。 對于什么是全棧開發(fā)者并沒有一個(gè)明確的定義。但是,有一件事是肯定的:2019 年對全棧開發(fā)者的需求量很大。在本文中,我將向你概述一些趨勢,你可以嘗試根據(jù)這些趨勢來確定你可能要投入的...

    NervosNetwork 評論0 收藏0
  • “別更新了,學(xué)不動了” 之:全棧開發(fā)者 2019 應(yīng)該學(xué)些什么?

    摘要:但是,有一件事是肯定的年對全棧開發(fā)者的需求量很大。有一些方法可以解決這個(gè)問題,例如模式,或者你可以這么想,其實(shí)谷歌機(jī)器人在抓取單頁應(yīng)用程序時(shí)沒有那么糟糕。谷歌正在這方面努力推進(jìn),但不要指望在年會看到任何突破。 對于什么是全棧開發(fā)者并沒有一個(gè)明確的定義。但是,有一件事是肯定的:2019 年對全棧開發(fā)者的需求量很大。在本文中,我將向你概述一些趨勢,你可以嘗試根據(jù)這些趨勢來確定你可能要投入的...

    sutaking 評論0 收藏0
  • “別更新了,學(xué)不動了” 之:全棧開發(fā)者 2019 應(yīng)該學(xué)些什么?

    摘要:但是,有一件事是肯定的年對全棧開發(fā)者的需求量很大。有一些方法可以解決這個(gè)問題,例如模式,或者你可以這么想,其實(shí)谷歌機(jī)器人在抓取單頁應(yīng)用程序時(shí)沒有那么糟糕。谷歌正在這方面努力推進(jìn),但不要指望在年會看到任何突破。 對于什么是全棧開發(fā)者并沒有一個(gè)明確的定義。但是,有一件事是肯定的:2019 年對全棧開發(fā)者的需求量很大。在本文中,我將向你概述一些趨勢,你可以嘗試根據(jù)這些趨勢來確定你可能要投入的...

    ormsf 評論0 收藏0
  • 精讀《JS 引擎基礎(chǔ)之 Shapes and Inline Caches》

    摘要:概述的解釋器優(yōu)化器代碼可能在字節(jié)碼或者優(yōu)化后的機(jī)器碼狀態(tài)下執(zhí)行,而生成字節(jié)碼速度很快,而生成機(jī)器碼就要慢一些了。比如有一個(gè)函數(shù),從獲取值引擎生成的字節(jié)碼結(jié)構(gòu)是這樣的指令是獲取參數(shù)指向的對象,并存儲在,第二步則返回。 1 引言 本期精讀的文章是:JS 引擎基礎(chǔ)之 Shapes and Inline Caches 一起了解下 JS 引擎是如何運(yùn)作的吧! JS 的運(yùn)作機(jī)制可以分為 AST 分...

    Tecode 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<