Typierte Webkomponenten bieten Ihnen einen kesselfreien, typisch-basierten Weg, um native Polymermodule (Polymer Toolbox Friendly) zu schreiben. Der gesamte Prozess erfolgt in der Entwurfszeit, sodass dem Projekt keine zusätzliche Abhängigkeit hinzugefügt werden muss.
npm install -g twc
TWC kommt mit der CLI. Der größte Teil seiner Konfiguration stammt von tsconfig
(und bower.json
) und funktioniert so ziemlich genauso wie TSC. Um TS -Klassen in native Polymermodule umzuwandeln, geben Sie einfach die Projektroamm -DIR ein und führen Sie Folgendes im Terminal aus:
twc
Es funktioniert genauso wie tsc
und liest die Konfiguration aus der Datei tsconfig.json
. Der einzige Unterschied besteht darin, dass es .html
-Dateien mit Polymermodul anstelle von einfachen .js
ausgibt.
Anmerkungen sind im @types
NPM -Namespace erhältlich. Bis zu diesem Fall müssen Typen in Tsconfig enthalten sein:
{
"compilerOptions": {
...
},
"files": [
...
],
"include": [
"node_modules/twc/types/polymer.decorators.d.ts"
]
}
TWC ermöglicht es, denselben Code entweder in Polymer 1.x oder Polymer 2.x zu kompilieren. Vor dem Kompilieren wird bower.json
auf Polymerabhängigkeitsversion überprüft und dann als Ziel verwendet. Zum Beispiel:
"polymer": "Polymer/polymer#^1.8.0"
baut ein Polymer 1.x -Modul, während dieses:
"polymer": "Polymer/polymer#^2.0.0"
Erstellt ein ES6 -Basis -Polymer 2.x -Modul.
Typscript -Compiler -Optionen sind auch für TWC verfügbar, aber nicht alles wird unterstützt. Hier ist eine Liste der nicht unterstützten Optionen (möglicherweise möglicherweise in Zukunft ändern):
Module in TWC umfassen die Syntax und die Schlüsselwörter der Typscript -Sprache und sind einfach nur Klassen. Konventionen, die folgen, entsprechen den Polymer 2.x (V1 -Webkomponenten -Spezifikation).
@ CustomElement ( )
export class MyElement extends Polymer . Element {
name : string ;
}
gleich
<dom-module id="my-element">
<script>
Polymer({
is: "my-element",
properties: {
name: {
type: String
}
}
});
</script>
</dom-module>
Es gibt 4 Möglichkeiten, eine Vorlage hinzuzufügen (damit sich niemand langweilen):
@template
Decorator an@template
Decorator antemplate()
zurück Der erste Ansatz ist sehr häufig und Sie haben dies wahrscheinlich mehrmals gesehen. Alles, was normalerweise zwischen <template>
Tags reichen würde, würde jetzt in den Dekorateur gehen. Keine ausgefallene Magie hier.
@ CustomElement ( )
@ template ( `<h1>Hello [[name]]</h1>` )
export class MyElement extends Polymer . Element {
name : string ;
}
In ähnlicher Weise müssen Sie nur einen relativen Pfad zur Vorlage bereitstellen (so wie Sie ihn über <link rel="import">
Tag importieren würden). Der Inhalt der Vorlagendatei sollte wie im ersten Ansatz - Code zwischen <template>
Tags sein.
@ CustomElement ( )
@ template ( 'template.html' )
export class MyElement extends Polymer . Element {
name : string ;
}
Wenn Sie mehr aus einer React -Welt kommen, mögen Sie die render()
-Methode. Hier ist es also eine template()
-Methode, die sehr gleich funktioniert. Der Vorteil dieser Methode besteht darin, dass Sie Zugriff auf den Klassenprototyp haben und sie in einer Vorlagenzeichenfolge verwenden können. Jeder this
Ausdruck wird durch eine Zwei-Wege-Bindung an die Eigenschaft ersetzt (wenn Sie einen Vorschlag haben, zu bestimmen, wann Sie eine Zwei-Wege-Verwendung verwenden und wann Sie eine Einwegbindung verwenden sollen, lassen Sie es mich bitte wissen).
@ CustomElement ( )
export class MyElement extends Polymer . Element {
name : string ;
template ( ) {
return `<h1>Hello ${ this . name } </h1>` ;
}
}
Der endgültige Ansatz besteht darin, die Klasse so zu verlassen und eine Vorlagendatei mit demselben Namen wie die TS -Datei zu erstellen. Bei der Kompilierzeit nimmt TWC den Dateiinhalt auf und fügt ihn an (genau wie bei einem zweiten Ansatz). Sei aber vorsichtig! Wenn Sie Outdir nicht angeben, können endgültige Module die Vorlagen ersetzen (standardmäßig generiert sie eine HTML -Datei mit demselben Grundnamen).
Bitte beachten Sie, dass TWC Polymervorlagen verwendet. Weitere Informationen zu Vorlagen und Bindung finden Sie unter diesen Dokumenten.
ES -Importe funktionieren noch nicht in den Browsern. Stattdessen verwendet Polymer die HTML -Importe. Auf diese Weise können wir <link>
-Tags zum Importieren von Modulen verwenden, aber wie machen wir das in TWC?
import "./my-component.html";
Das gleiche Prinzip gilt für Skripte (konvertiert in <script>
Tags):
import "./some-library.js";
Die oben genannten werden zusammengestellt
<link rel="import" href="./my-component.html">
Und
<script src="./some-library.js"></script>
jeweils.
Die Umgang mit relativen Wegen zu Bower- oder NPM -Repositories kann schmerzhaft sein. Hier sind Aliase nützlich:
import "bower:polymer/polymer-element.html";
import "npm:jquery/dist/jquery.min.js";
Das obige wird übersetzt, um das Bower -Verzeichnis von .bowerrc
zu verwenden, und fällt auf bower_components
zurück. Da die meisten Entwickler polymer-cli
verwenden, um die Komponenten zu bedienen, werden Pfade zu bower_components
in den als ob das Projektrouch in diesem Ordner übersetzt.
Wenn Sie aus irgendeinem Grund die Namen oder Pfade der NPM- oder Bower -Ordner ändern müssen, können Sie dies tun, indem Sie die Umgebungsvariablen bowerDir
und npmDir
einstellen.
Es ist auch möglich, relativ zur Projektwurzel zu importieren. Fügen Sie einfach ein ~
vor dem Pfad hinzu:
import "~demo/index.html";
import "~bower_components/polymer/polymer-element.html";
Verwenden Sie die ES -Importe, um Mitglieder anderer Module zu importieren (z. B. ein Verhalten importieren):
import { IronControlState } from "bower:iron-behaviors/iron-control-state.html";
Wenn in den Definitionen ein Namespace deklariert ist, wird automatisch alle Instanzen des importierten Mitglieds aktualisiert.
Bitte beachten Sie , dass Sie das Import von HTML -Modulen zulässt. Sie müssen Definitionen generieren.
Verwenden Sie das Potts -Tool, um die Typdeklarationen aus vorhandenen Verhaltensweisen/Komponenten zu generieren. Installieren Sie es einfach global ( npm install potts -g
) und führen Sie potts
im Projekt Root -Verzeichnis aus. Deklarationen werden standardmäßig in der Datei potts.d.ts
gespeichert (konfigurierbar über --outFile
oder -o
-Flag). Dadurch werden Deklarationen für alle HTML -Dateien im main
der bower.json
-Datei jeder Bower -Abhängigkeit generiert. Alle Module werden so deklariert, dass sie mit dem importierbaren Pfad übereinstimmen (z. B. bower:polymer/polymer.html
).
Jedes solide Projekt sollte eine ordnungsgemäße Dokumentation haben. Dies umfasst auch Dokumentation von Ereignissen, die von der Komponente abgefeuert wurden. Mit TWC können Sie dies mit Leichtigkeit tun, indem Sie eine Schnittstelle erstellen, die Event
oder CustomEvent
erweitert.
/** My custom event, which fires when needed */
export interface SomeEvent extends CustomEvent {
detail: {
/** Property inside event.detail */
myCustomProp: string;
};
}
Jeder Wert, der direkt zur Eigenschaftserklärung eingestellt ist, wird als Standardwert verwendet. Jeder nicht primitive Wert (Array, Objekt usw.) wird mit einer Funktion verpackt:
export class MyElement {
title : string = '' ;
categories : Array = [ ] ;
}
wird übersetzt werden
Polymer ( {
properties : {
title : {
type : string ,
value : ''
} ,
categories : {
type : Array ,
value : function ( ) {
return [ ] ;
}
}
}
} ) ;
Nicht alles sollte zur properties
hinzugefügt werden. Um diesen Prozess zu überspringen, muss Eigentum als privat definiert werden:
export class MyElement {
name : string ; // is added to properties config
private hasName : boolean ; // is NOT added to properties config
}
Nicht alles in Polymer kann mit TypeScript -Schlüsselwörtern durchgeführt werden, aber die einzige Eigenschaft ist so einfach wie das Vorieren von readonly
:
export class MyElement {
readonly name : string ; // property will have `readOnly` flag
}
ES -Mixins werden seit Typscript 2.2 unterstützt. Sie können hier mehr darüber lesen.
Mixins werden nicht von Polymer V1 unterstützt
Verhaltensweisen sind der erste Ansatz zur gemeinsamen Nutzung der Funktionalität in Polymer (jetzt durch ES -Mixins ersetzt). Sie werden als einfache Objekte mit Polymereigenschaften und Methoden definiert, die genau wie bei Polymer V1 -Konfigurationsobjekt aufgeführt sind. Um ein Verhalten hinzuzufügen, verwenden Sie das Polymer.mixinBehaviors()
Mixin (weitere Informationen hier). Für Polymer V1 werden sie zur Verhaltenskonfiguration hinzugefügt, während Polymer V2 sie mit oben mischt.
Wie bereits erwähnt, kann nicht alles mit Keywords erfolgen. Aus diesem Grund verfügt TWC mit einer Reihe von Anmerkungen zur Designzeit.
Um sie zu verwenden, installieren Sie TWC lokal und importieren nach Bedarf in Elements Quelldateien:
import { attr , compute , notify , observe , style , template } from 'twc/polymer' ;
Um Ihrer Komponente einen Körper zu geben, müssen Sie ihn mit einer Vorlage zur Verfügung stellen. Dies erfolgt mit @template
Annotation, die entweder den HTML -Vorlagencode oder einen Pfad zur HTML -Vorlage akzeptiert (muss eine .html
-Erweiterung haben).
@ template ( `<h1>Hello {{name}}</h1>` )
export class MyElement {
name : string ;
}
@ template ( `template.html` )
export class MyElement {
name : string ;
}
Das Styling der Komponente ist so einfach wie eine Vorlage zu geben. @style
Annotation akzeptiert CSS -Code, CSS -Dateipfad oder freigegebener Stilname. Eine einzelne Komponente können mehrere Stile zur Verfügung gestellt werden.
@ template ( `<h1>Hello {{name}}</h1>` )
@ style ( `:host {display: block;}` , `style.css` , `shared-styles` )
export class MyElement {
name : string ;
}
@attr
und @notify
add reflectToAttribute
und notify
von Flags an properties
.
export class MyElement {
@ attr ( ) name : string ; // property will have `reflectToAttribute` flag
@ notify ( ) age : number ; // property will have `notify` flag
}
Berechnete Eigenschaften sind Eigenschaften, die eine oder mehrere Abhängigkeiten (beobachtete Eigenschaften) kombinieren. Immer wenn sich die Abhängigkeit ändert, wird der Eigenschaft eine berechnete Eigenschaftsmethode abfeuert und zurückgegeben. Weitere Informationen hier. TWC ermöglicht es, sie auf zwei Arten zu erstellen: Durch die Bereitstellung eines Funktionsnamens und des Abhängigkeits -Arrays oder durch direkte Übergabe einer Resolver -Funktion können Abhängigkeiten in einem Array von Zeichenfolgen oder als Funktionsargumente übergeben werden).
export class MyElement {
name : string ;
age : number ;
cards : Array < string > ;
// Responds to `name` changes. Property name taken from function argument.
@ compute ( ( name : string ) => `Hi, I am ${ name } ` ) greetings : string ;
// Responds to `age` changes. Property name taken from an array.
@ compute ( ( value : number ) => value >= 18 , [ "age" ] ) isAdult : boolean ;
// Responds to both `age` and `name` changes.
@ compute ( ( age : number , name : string ) => ` ${ name } is ${ age } years old` ) aboutMe : string ;
// Responds to length of `cards` array changes. As dependency is a path, it has to be added to an array.
@ compute ( ( size ) => size , [ "cards.length" ] ) collectionSize : number ;
// Responds to name and length of `cards` array changes. Resolver method is provided by name.
@ compute ( '_summary' , [ "name" , "cards.length" ] ) summary : string ;
private _summary ( name , collectionSize ) {
return ` ${ name } has ${ collectionSize } cards` ;
}
}
Sie können nicht nur durch berechnete Eigenschaften, sondern auch durch Beobachter auf jede Eigenschaft oder Pfadänderungen reagieren. Der Beobachter gibt nichts zurück und dies ist der einzige Unterschied zwischen ihnen.
export class MyElement {
name : string ;
cards : Array < string > ;
// Responds to name and length of `cards` array changes.
@ observe ( "name" , "cards.length" ) summary ( name , collectionSize ) {
console . log ( ` ${ name } cards collection size changed to ${ collectionSize } cards` ;
}
}
Typierte Webkomponenten befinden sich in einer frühen Phase und benötigen Ihr Feedback. Bitte probieren Sie es aus und wenn Sie ein Problem finden, posten Sie es in Problemen. Zögern Sie auch nicht, auch Ideen zu veröffentlichen!
classList
) Um Tests unter Windows ( npm run test
) auszuführen, müssen derzeit den Abschnitt der Datei tsconfig.json
include
werden, damit das folgende Muster enthält:
{
"include" : [
" node_modules/@types/**/*.d.ts "
]
}