天天看點

了解Angular Ivy: Incremental DOM 和 Virtual DOM

Angular Ivy 作為Angular 的最新渲染引擎,與我們看到的當今所有主流架構的引擎有根本不同,因為Angular Ivy使用了Incremental DOM(增量DOM).

什麼是 incremental DOM?它與virtual DOM有何不同?

讓我們對他們做下比較,看看為什麼Angular 要使用Incremental DOM

Virtual DOM 的工作原理

React是第一個使用virtual DOM的主流架構,它的設計思想是:

每個元件在每次渲染時建立一個新的virtual DOM.React把新的Virtual DOM樹

與現有的相比較,然後将一系列轉變應用于浏覽器DOM,進而比對新的Virtual DOM樹。

了解Angular Ivy: Incremental DOM 和 Virtual DOM

Virtual DOM有兩個主要優點:

  • 我們可以使用任何語言去實作元件渲染,是以我們不需要重新編譯任何東西。React 開發者主要使用JSX,但我們使用原生的JavaScript一樣可以做到。
  • 作為渲染元件的結果,我們得到一個值。它可以被用來測試,debug等。

Incremental DOM

Incremental DOM 被Google内部使用,它的主要設計思想為:

每個元件都被編譯成一系列指令。這些指令建立DOM樹并在資料更改時就地更新它們.

例如下面一個元件

@Component({
  selector: 'todos-cmp',
  template: `
    <div *ngFor="let t of todos|async">
        {{t.description}}
    </div>
  `
})
class TodosComponent {
  todos: Observable<Todo[]> = this.store.pipe(select('todos'));
  constructor(private store: Store<AppState>) {}
}
           

會被編譯成:

var TodosComponent = /** @class */ (function () {
  function TodosComponent(store) {
    this.store = store;
    this.todos = this.store.pipe(select('todos'));
  }

  TodosComponent.ngComponentDef = defineComponent({
    type: TodosComponent,
    selectors: [["todos-cmp"]],
    factory: function TodosComponent_Factory(t) {
      return new (t || TodosComponent)(directiveInject(Store));
    },
    consts: 2,
    vars: 3,
    template: function TodosComponent_Template(rf, ctx) {
      if (rf & 1) { // create dom
        pipe(1, "async");
        template(0, TodosComponent_div_Template_0, 2, 1, null, _c0);
      } if (rf & 2) { // update dom
        elementProperty(0, "ngForOf", bind(pipeBind1(1, 1, ctx.todos)));
      }
    },
    encapsulation: 2
  });

  return TodosComponent;
}());
           

模闆函數包含了渲染和更新DOM的指令。架構的渲染引擎不會解釋指令,因為這些指令就是引擎。

為什麼選擇Incremental DOM

為什麼Google的工程師使用Incremental DOM來代替Virtual DOM呢?

一個目标在他們心中萦繞:應用必須在手機端表現良好。這就意味着要在兩個方面進行優化:

  • 檔案大小
  • 記憶體占用

要實作這兩個目标,

  • 渲染引擎自身必須是 tree shakable 的。
  • 渲染引擎必須具有較低的記憶體開銷
Tree Shakable

當使用 Incremental DOM時,架構不會編譯元件,而是元件引用指令。如果元件未使用特定指令,它就永遠不會被使用。是以,我們可以省略掉bundle中未使用的指令。

了解Angular Ivy: Incremental DOM 和 Virtual DOM

Virtual DOM需要一個解釋器。在編譯時,根本無法确定編譯器各個部分是否被使用,是以我們需要把所有東西都發送到浏覽器。

了解Angular Ivy: Incremental DOM 和 Virtual DOM

低記憶體開銷

每次重新渲染時,Virtual DOM都會從頭開始建立整個樹。

了解Angular Ivy: Incremental DOM 和 Virtual DOM

而Incremental DOM,在視圖未改變時,是不需要任何記憶體的。我們隻有在添加或删除DOM時需要配置設定記憶體。并且配置設定的記憶體大小與改變的DOM的大小成正比。

了解Angular Ivy: Incremental DOM 和 Virtual DOM

由于大多數模闆或渲染調用不會改變任何東西,或改變很少,是以可以節省大量記憶體。

更多功能

具有渲染傳回值可以提供更多用途,譬如測試。另一方面能夠使用FireFox DevTools逐行使用指令,使調試和性能分析更容易。

Ivy和 Incremental DOM

Angular一直在使用HTML和Templates.這也是virtual DOM 未被Angular所接受的原因。

鑒于此,加上Incremental DOM的低記憶體開銷和Tree Shakable .我認為使用Incremental DOM作為渲染引擎是正确的選擇。

文章原文來自NRWL