亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Angular如何由模板生成DOM樹(shù)的方法

 更新時(shí)間:2019年12月23日 08:57:31   作者:朱玉潔  
這篇文章主要介紹了Angular如何由模板生成DOM樹(shù)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

Angular等現(xiàn)代Web框架極大的提高了開(kāi)發(fā)效率,比如我們經(jīng)常會(huì)在開(kāi)發(fā)過(guò)程中寫(xiě)出類似下面的代碼:

<div>
  {{title}}
</div>

export class AppComponent {
 title = 'angular';
}

這種模板寫(xiě)法并不是HTML原生支持的,那么Angular又是如何轉(zhuǎn)換這些代碼,并顯示成我們期望的界面呢? 首先我們來(lái)看看Angular把上述代碼編譯成什么樣子:

 ...省略了其他代碼
 i0.ɵɵelementStart(0, "div");
 i0.ɵɵtext(1, " hello angular\n");
 i0.ɵɵelementEnd()
 ...省略了其他代碼

可以看到,Angular把我們寫(xiě)的模板編譯成指令的方式,然后通過(guò)這些指令生成對(duì)應(yīng)的HTML.這個(gè)過(guò)程包含兩個(gè)步驟:

  1. 把模板編譯成上面的產(chǎn)物
  2. 執(zhí)行產(chǎn)物代碼生成HTML

本文主要圍繞步驟二進(jìn)行展開(kāi),步驟一的話可能會(huì)在后續(xù)另寫(xiě)一篇進(jìn)行闡述。

觀察上面的產(chǎn)物代碼,我們不難發(fā)現(xiàn)有三個(gè)主要方法:elementStart、text、elementEnd.從它們的命名不難推測(cè),這三個(gè)方法的作用分別是開(kāi)始生成標(biāo)簽、內(nèi)容賦值、閉合標(biāo)簽。下面我們來(lái)嘗試自己實(shí)現(xiàn)這幾個(gè)方法,最簡(jiǎn)單的基礎(chǔ)版本大概會(huì)是這樣:

let currentNode: Node | null = null;
let currentParent: Node | null = null;

function patch(host: Node | DocumentFragment, render: () => void): void {
  currentNode = host;
  render();
}

function elementOpen(tagName: string): void {
  currentParent = currentNode;
  const element = document.createElement(tagName);
  currentParent!.appendChild(element);
  currentNode = element;
}

function text(textContent: string): void {
  currentNode!.textContent = textContent;
}

function elementEnd(tagName: string): void {
  currentNode = currentParent;
  currentParent = currentNode!.parentNode;
}

然后在HTML中可以這樣使用:

 <div id="container"></div>
 <script>
 function render() {
  elementOpen('div');
  text('div content');
   elementOpen('p');
   text('p content');
   elementEnd('p');
  elementEnd('div');
 }
 patch(document.getElementById('container'), render);
 </script>

上述代碼中,text方法參數(shù)都被寫(xiě)固定了,實(shí)際生成的代碼可能類似于text(Comp.title)這種形式。那么既然是以變量的形式賦值,當(dāng)用戶進(jìn)行操作的時(shí)候,更新這個(gè)變量的值,豈不是又要完全重新執(zhí)行一遍patch函數(shù)么?我們知道DOM操作是耗時(shí)的,當(dāng)我們的項(xiàng)目較大時(shí),如果不采取優(yōu)化措施,勢(shì)必會(huì)影響框架性能。為此我們很容易想到的一個(gè)優(yōu)化思路,在再次執(zhí)行patch函數(shù)時(shí),如果DOM節(jié)點(diǎn)已經(jīng)存在我們就重復(fù)利用,不再去重新創(chuàng)建并插入DOM樹(shù)?;谶@個(gè)思路,我們來(lái)更新一下代碼:

let currentNode: Node | null = null;
let currentParent: Node | null = null;


function patch(host: Node | DocumentFragment, render: () => void): void {
  currentNode = host;
  render();
}

function elementOpen(tagName: string): void {
  currentParent = currentNode;

  const firstChild = (currentParent as Element).firstElementChild;
  if (firstChild && firstChild.tagName.toLowerCase() === tagName) {
    currentParent = firstChild;
    return;
  }

  const element = document.createElement(tagName);
  currentParent!.appendChild(element);
  currentNode = element;
}

function text(textContent: string): void {
  if (currentNode!.textContent !== textContent) {
    currentNode!.textContent = textContent;
  }
}

function elementEnd(tagName: string): void {
  currentNode = currentParent;
  currentParent = currentNode!.parentNode;
}

本文所述代碼,只是表述Angular由模板生成dom樹(shù)的大致思路。具體的Angular做了許多優(yōu)化,而且它實(shí)現(xiàn)細(xì)節(jié)也和本文有區(qū)別。不同于現(xiàn)今較為流行的virtual DOM實(shí)現(xiàn)方式,Angular這種實(shí)現(xiàn)思路不需要單獨(dú)創(chuàng)建中間DOM對(duì)象,減少了內(nèi)存分配。對(duì)此感興趣的讀者可以自行去看Angular的實(shí)現(xiàn)。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論