Hallo. Mein Name ist Roman und ich bin nicht der Erfinder von Fahrrädern. Ich mag das Angular-Framework und das Ökosystem um es herum und entwickle meine Webanwendungen damit. Aus meiner Sicht basiert der Hauptvorteil von Angular auf lange Sicht auf der Trennung von Code zwischen HTML und TypeScript, die von einem seiner Entwickler ausführlich beschrieben wurde und die Komplexität des dynamischen Kompilierens von Komponenten zur Laufzeit. Daher möchte ich die bekannte Angular-Vorlagensyntax verwenden, um dem Benutzer die Möglichkeit zu geben, Briefvorlagen anzupassen, Berichte und Tabellen zum Drucken zu erstellen oder das Exportformat für XML-Dateien festzulegen! Um herauszufinden, wie das geht, willkommen bei cat!
Herausforderung
Im Allgemeinen kann die Verwendung von Angular-Vorlagen durch den Benutzer folgendermaßen aussehen: Wir haben einen bestimmten Datensatz:
const data = { project: 'MySuperProject', userName: 'Roman', role: 'admin', projectLink: 'https://example.com/my-super-projectproject' }
Es ist erforderlich, die Möglichkeit zu geben, den Text des Briefes anzupassen, der nach der Bearbeitung des Projekts an den Benutzer gesendet wird. Bei Verwendung einer Winkelvorlage könnte dies folgendermaßen aussehen:
<body> ! {{project}} <a href="{{projectLink}}">3D </a> <div *ngIf="role == 'admin'"> <a href="{{projectLink}}?mode=edit"></a> </div> </body>
Ng-Template-Bibliothek
Dieses Problem kann mit dem Angular-Compiler auf dem Client (oder sogar auf der Serverseite) gelöst werden, ist jedoch sehr zeitaufwändig und erfordert das Ziehen vieler Megabyte Code auf den Client. Warum ist der Angular-Compiler so groß? Dies liegt an der Tatsache, dass es eine Vielzahl von Funktionen zum Erstellen von Komponenten und Modulen unterstützt und auch einen eigenen HTML-Parser enthält! Deshalb habe ich beschlossen, einen minimalen Angular-Vorlagenkonverter zu schreiben, der den im Browser integrierten HTML-Parser verwendet. Mit nur wenigen Codezeilen war dies in nur wenigen Stunden in wenigen Stunden möglich. Ich habe beschlossen, das Ergebnis auf
GitHub der Öffentlichkeit zugänglich zu machen
Die Verwendung der ng-Template-Bibliothek ist ganz einfach:
Installieren Sie die Abhängigkeit von npm
npm install --save @quanterion/ng-template
oder durch Garn
yarn add @quanterion/ng-template
Und verwenden Sie es wie folgt:
import { compileTemplate, htmlToElement } from '@quanterion/ng-template'; async test() { let data = { name: 'Roman' }; let element = htmlToElement(`<div>{{name}}</div>`); await compileTemplate(element, data); alert(element.outerHTML); }
Unterstützte Syntax
- Ausdrücke {{Ausdruck}} mit der Möglichkeit, auf Variablen zuzugreifen und Funktionen aufzurufen
- Ng-Vorlagen
- Ng-Behälter
- Bedingungen * ngIf + * ngIf as
- Zyklen * ngFür
- Styles [style.xxx] = "Wert" und [style.xxx.px] = "Wert"
- Bedingte Klassen [class.xxx] = "Wert"
- Observables {{name $}} mit automatischem Abonnement eines Werts (als asynchrone Pipe)
Weitere Informationen finden Sie unter
ng-template.spec.ts- Tests.
Eval verwenden
Um Ausdrücke in Vorlagen auszuwerten, wird eval mit Präferenz und Kurtisanen verwendet. Tatsache ist, dass in Angular-Vorlagen der Zugriff auf Variablen ohne das übliche JavaScript-Präfix verwendet wird. Daher müssen Sie eval () aufrufen, das alle Variablen des Datenobjekts im Gültigkeitsbereich enthält. Es ist mir nicht gelungen, einen solchen Code für eval () zu generieren, weil Code anzeigen
const data = { a: 1, b: () => 4 }; const expression = 'a+b()'; eval('a =1; b = ??;' + expression);
erlaubt keine Übergabe von Funktionen
Die Lösung wurde gefunden, indem eine Funktion erstellt wurde, deren Parameter die Feldnamen des Objekts mit Daten enthalten:
const data = { a: 1, b: () => 4 }; let entries = [] for (let property in data ) { entries.push([property, data[property]]) } const params = entries.map(e => e[0]); const fun = new Function('code', ...params, `return eval(code)`); const args = entries.map(e => e[1]); const expression = 'a+b()'; const result = fun.call(undefined, expression , ...args);
PS: Ich hoffe, dass es in Zukunft, wenn sich die API des neuen Ivy-Compilers stabilisiert, möglich sein wird, eine Reihe von Operatoren für Ivy zu generieren und vollwertige Komponenten in der Dynamik zu erstellen!
Link zur Quelle