@seanox/aspect-js
Version:
full stack JavaScript framework for SPAs incl. reactivity rendering, mvc / mvvm, models, expression language, datasource, virtual paths, unit test and some more
150 lines (115 loc) • 5.38 kB
Markdown
[Komponenten](composite.md) | [Inhalt](README.md#reaktives-rendering) | [Erweiterung](extension.md)
- - -
# Reaktives Rendering
Beim reaktiven Ansatz lösen Änderungen an den Datenobjekten (Models)
ein partielles Auffrischen der Konsumenten in der View aus. Konsumenten sind
alle Ausdrücke, die lesend auf den geänderten Wert eines Datenobjekts
zugreifen. In der View lassen sich Ausdrücke in den HTML-Elementen und im
Freitext verwenden. Die Datenobjekte müssen dann für das reaktive
Rendering `Reactive(object)` oder `Object.prototype.reactive()` nutzen.
```javascript
const Model = {
value: ...
}.reactive();
```
In diesem Beispiel aktualisiert der Renderer automatisch alle HTML-Elemente im
DOM, was Freitexte einschliesst, welche die Eigenschaft `value` vom `Model`
direkt oder indirekt in einem Ausdruck verwenden, wenn sich der Wert der
Eigenschaft `value` ändert oder genauer, wenn ein geänderter Wert im
Datenobjekt final gesetzt wurde, was bei der Verwendung von Getter und Setter
relevant sein kann.
__Das reaktive Verhalten basiert auf Notifications innerhalb von Reactive mit
denen das Rendering angesteuert wird. Damit die Notifications eingerichtet
werden können, muss Reactive die Konsumenten der Daten kennen, wozu es die
erforderlichen Informationen beim Parsen und Rendern vom Markup sammelt, was
auch für Markup funktioniert, welches erst zur Laufzeit eingefügt
wird. Somit muss Reactive immer vor den Konsumenten existieren.__
Beenden lässt sich das reaktive Rendering durch das gezielte Löschen
von Reactive-Instanzen mit der `delete` Methode.
Reactive wirkt permanent rekursiv auf allen Objektebenen und auch auf die
Objekte welche später als Wert hinzugefügt werden. Auch wenn diese
Objekte nicht explizit Reactive nutzen, werden für die referenzierten
Objekte neue Instanzen gebildet. Initiierende Objekte und reaktive Models sind
logisch entkoppelt und werden bidirektional synchronisiert. Im Unterschied dazu
nutzen Views und reaktive Models, wie auch die Models intern, Proxies, die sich
wie die initiierenden Originale verhalten und verwenden lassen. Jedoch sind
Proxies eigenst&aumkl;ndige Instanzen, die kompatibel aber nicht identisch zum
initiierenden Objekt sind. Notwendig ist diese logische Trennung, damit der
Renderer bei Datenänderungen entsprechende Notifications erzeugen und damit
die Konsumenten in der View aktualisieren kann.
```javascript
const objectA = {}
const objectB = {}
objectA.objectB = objectB;
// Assertions
objectA.objectB === objectB
const objectC = objectA.reactive();
// Assertions
objectC.objectB !== objectA
objectC.objectB !== objectB
objectA.objectB === objectB
const objectD = ({}).reactive();
objectD.objectB = objectB;
objectD.objectB.text = "A";
// Assertions
objectD.objectB !== objectB;
objectD.objectB === objectC.objectB;
objectD.objectB.text === "A";
objectC.objectB.text === "A";
const objectE = {text: "A"};
const objectF = objectE.reactive();
objectF.text = "B";
// Assertions
objectE.text === "B";
objectF.text === "B";
objectE.text = "C";
// Assertions
objectE.text === "C"
objectF.text === "C"
```
__Reactive ist ein Stellvertreter (Substitute) für ein anderes Objekt und
kontrolliert den Zugriff auf das ursprüngliche Objekt. Auch wenn Reactive
und das Objekt eigenständige Instanzen sind, ist Reactive fest an das
ursprüngliche Objekt gebunden und dennoch entkoppelt.__
```javascript
const objectA = {};
const objectB = objectA.reactive();
objectB.value = "B";
// Assertions
typeof objectA.value === "string"
typeof objectB.value === "string"
objectA.value === objectB.value
```
Von einer bestehenden Reactive-Instanz kann keine neue Reactive-Instanz
erstellt werden. `ReactProxy.prototype.reactive()` wird immer eine Referenz
auf sich selbst zurückgeben. Etwas anders verhält es sich, wenn einer
bestehenden ReactProxy-Instanz ein anderes ReactProxy-Objekt als Wert
hinzugefügt wird. Dann wird auf Basis vom ursprünglichen Objekt, das
als ReactProxy-Objekt hinzugefügt werden soll, eine neue ReactProxy-Instanz
erstellt.
```javascript
const objectA = ({}).reactive();
const objectB = objectA.reactive();
const objectC = Reactive(objectA);
// Assertions
objectA === objectB
objectA === objectC
objectB === objectC
const objectD = ({objectA}).reactive();
// Assertion
objectD.objectA === objectA
objectC.objectB = objectB;
// Assertion
objectC.objectB === objectB
```
__Missverständnisse vorbeugen__
Der ReactProxy selbst hat keinen direkten Einfluss auf die View, sondern fordert
den Renderer auf, einzelne konsumierende HTML-Elemente zu aktualisieren, was
besonders dann beachtet werden muss, wenn Ausdrücke temporäre
Variablen nutzen, wie sie z.B. beim Attribut `iterate` verwendet werden.
HTML-Elemente mit dem Attribut`iterate` werden automatisch berücksichtigt
und so wird in diesem Fall immer das oberste HTML-Element mit dem Attribut
`iterate` aktualisiert, damit die temporären Variablen in allen
Ausdrücken verfügbar sind.
- - -
[Komponenten](composite.md) | [Inhalt](README.md#reaktives-rendering) | [Erweiterung](extension.md)