Listings Hanschke/Rendering-Engines


Listing 1: Eine naive Rendering-Engine
class Renderer {
    constructor(render, state) {
      this.render = render;
      this.updateDom(state);
    }

    setState(state) {
      this.updateDom(state);
    }

    updateDom(state) {
      document.body.innerHTML = this.render(state);
    }
}

const app = new Renderer(function (state) {
    return `<h1>Hello ${state.name}</h1>`;
}, { name: 'Max' });

setTimeout(() => {
    app.setState({ name: 'Moritz' });
}, 1000);

-----

Listing 2: DOM höchstens einmal pro Frame aktualisieren

updateDom(state) {
    this.currentState = state;

    if (!this.updateScheduled) {
      window.requestAnimationFrame(() => {
        document.body.innerHTML = this.render(this.currentState);
        this.updateScheduled = false;
      });
      this.updatedScheduled = true;
    }
}

-----

Listing 3: Bedingte Anweisungen und Schleifen in Angular-Templates
<h1>Aufgaben</h1>
<ul *ngIf="hasTodos">
    <li *ngFor="let todo of todos" [class]="todo.status">{{todo.text}}</li>
</ul>

-----

Listing 4: Angular-Compiler übersetzt das Template in Instruktionen
import ng from '@angular/core';

function HelloWorldComponent_Template(rf, ctx) {
    // Initiales Rendering des statischen Anteils
    if (rf & 1) {
      ng.ɵɵelementStart(0, "div");                                     // <div>
      ng.ɵɵtext(1);                                                    // Count: {{count}}
      ng.ɵɵelementEnd();                                               // </div>
      ng.ɵɵelementStart(2, "button", 0);                               // <button
      ng.ɵɵlistener("click", function() { return ctx.increment(); });  // (click)="increment()">
      ng.ɵɵtext(3, "Increment");                                       // Increment
      ng.ɵɵelementEnd();                                               // </button>
    }
    // Rendering und Aktualisieren dynamischer Parts
    if (rf & 2) {
      ng.ɵɵadvance(1);                                                 // <div>
      ng.ɵɵtextInterpolate1("Count: ", ctx.count, "");                 // Count: {{count}}
    }
};

-----

Listing 5: Der Ember-Compiler übersetzt das Template in Bytecode für die Glimmer VM
[
    [10,"div"],
    [12],
    [2,"Count: "],
    [1,[32,0,["count"]]],
    [13],
    [2,"\\n"],
    [11,"button"],
    [4,[38,0],["click",[32,0,["incrementCount"]]],null],
    [12],
    [2,"increment count"],
    [13]
]

