Los componentes web escritos le brindan una forma basada en el mecanografiado y sin horario básico, para escribir módulos de polímero nativos (Polymer Toolbox Friendly). Todo el proceso se realiza en el tiempo de diseño, por lo que no se debe agregar dependencia adicional al proyecto.
npm install -g twc
TWC viene con la CLI. La mayor parte de su configuración proviene de tsconfig
(y bower.json
), y funciona más o menos que TSC. Para transformar las clases TS en módulos de polímero nativo, solo ingrese el directorio de la raíz del proyecto y ejecute lo siguiente en el terminal:
twc
Funciona solo como tsc
, leyendo la configuración del archivo tsconfig.json
. La única diferencia es emitir archivos .html
con módulo de polímero en lugar de .js
.
Las anotaciones estarán disponibles en el espacio de nombres @types
NPM. Hasta que esto suceda, los tipos deben incluirse en TSCONFIG:
{
"compilerOptions": {
...
},
"files": [
...
],
"include": [
"node_modules/twc/types/polymer.decorators.d.ts"
]
}
TWC permite compilar el mismo código en el polímero 1.x o el polímero 2.x. Antes de compilarse, bower.json
se verifica para la versión de dependencia de polímeros y luego se usa como objetivo. Por ejemplo:
"polymer": "Polymer/polymer#^1.8.0"
construirá un módulo de polímero 1.x, mientras que este:
"polymer": "Polymer/polymer#^2.0.0"
Construye un módulo 2.x de polímero basado en ES6.
Las opciones de compilador de mecanografiado también están disponibles para TWC, sin embargo, no todo es compatible. Aquí hay una lista de opciones no compatibles (eventualmente podría cambiar en el futuro):
Los módulos en TWC adoptan la sintaxis y las palabras clave del lenguaje mecanografiado, y son simplemente clases. Las convenciones para seguir coinciden con el polímero 2.x (especificación de componentes web v1).
@ CustomElement ( )
export class MyElement extends Polymer . Element {
name : string ;
}
iguales
<dom-module id="my-element">
<script>
Polymer({
is: "my-element",
properties: {
name: {
type: String
}
}
});
</script>
</dom-module>
Hay 4 formas de agregar una plantilla (para que nadie se aburra):
@template
@template
Decoratortemplate()
El primer enfoque es muy común y probablemente lo haya visto varias veces. Todo lo que normalmente iría entre las etiquetas <template>
, ahora entraría en el decorador. No hay magia elegante aquí.
@ CustomElement ( )
@ template ( `<h1>Hello [[name]]</h1>` )
export class MyElement extends Polymer . Element {
name : string ;
}
Del mismo modo, el segundo enfoque, solo necesita proporcionar una ruta relativa a la plantilla (tal como la importaría a través de <link rel="import">
etiqueta). El contenido del archivo de plantilla debe ser como en el primer enfoque: código entre las etiquetas <template>
.
@ CustomElement ( )
@ template ( 'template.html' )
export class MyElement extends Polymer . Element {
name : string ;
}
Si viene más de un mundo React, es posible que le guste el método render()
. Así que aquí está, un método template()
que funciona muy parecido. La ventaja de este método es que tiene acceso al prototipo de clase, y puede usarlo en una cadena de plantilla. Cada this
se reemplazará con unión de dos vías a la propiedad (si tiene una sugerencia de cómo determinar cuándo usar bidireccional y cuándo usar unión unidireccional, hágamelo saber).
@ CustomElement ( )
export class MyElement extends Polymer . Element {
name : string ;
template ( ) {
return `<h1>Hello ${ this . name } </h1>` ;
}
}
El enfoque final es dejar la clase tal como está y crear un archivo de plantilla, con el mismo nombre que el archivo TS. En el tiempo de compilación, TWC recogerá el contenido del archivo y lo adjuntará (al igual que con el segundo enfoque). ¡Ten cuidado! Si no especifica al aire libre, los módulos finales pueden reemplazar las plantillas (de forma predeterminada, generará un archivo HTML con el mismo nombre base).
Tenga en cuenta que TWC usa plantillas de polímeros. Para leer más sobre plantillas y vinculación, consulte estos documentos.
Las importaciones de ES aún no funcionan en los navegadores. En su lugar, el polímero usa las importaciones HTML. Esto nos permite usar etiquetas <link>
para importar módulos, pero ¿cómo lo hacemos en TWC?
import "./my-component.html";
El mismo principio se aplica a los scripts (convertido a <script>
etiquetas):
import "./some-library.js";
Los anteriores se compilan a
<link rel="import" href="./my-component.html">
y
<script src="./some-library.js"></script>
respectivamente.
El manejo de los caminos relativos a los repositorios de Bower o NPM puede ser doloroso. Aquí es donde los alias son útiles:
import "bower:polymer/polymer-element.html";
import "npm:jquery/dist/jquery.min.js";
Lo anterior se traducirá para usar el directorio de Bower desde .bowerrc
y recurrirá a bower_components
. Como la mayoría de los desarrolladores usarán polymer-cli
para servir a los componentes, las rutas a bower_components
se traducirán como si la raíz del proyecto estuviera dentro de esa carpeta.
Si por alguna razón necesita cambiar los nombres o rutas de la carpeta NPM o Bower, puede hacerlo configurando las variables de entorno bowerDir
y npmDir
.
También es posible importar en relación con la raíz del proyecto. Simplemente agregue un ~
frente al camino:
import "~demo/index.html";
import "~bower_components/polymer/polymer-element.html";
Para importar miembros de otros módulos (por ejemplo, importar un comportamiento), use las importaciones de ES:
import { IronControlState } from "bower:iron-behaviors/iron-control-state.html";
Si hay un espacio de nombres declarado en las definiciones, actualizará automáticamente todas las instancias de miembro importado.
Tenga en cuenta que para permitir la importación de los módulos HTML, debe generar definiciones.
Para generar las declaraciones de tipo a partir de comportamientos/componentes existentes, use la herramienta POTTS. Simplemente instálelo a nivel mundial ( npm install potts -g
) y ejecute potts
en el directorio de la raíz del proyecto. Las declaraciones se guardarán en el archivo potts.d.ts
de forma predeterminada (configurable a través de --outFile
o -o
Flag). Esto generará declaraciones para todos los archivos HTML escuchar en la sección main
del archivo bower.json
de cada dependencia de Bower. Se declarará todos los módulos que coincidan con la ruta importable (por ejemplo, bower:polymer/polymer.html
).
Cada proyecto sólido debe tener una documentación adecuada. Esto también incluye documentar eventos disparados por el componente. TWC le permite hacerlo con facilidad creando una interfaz que extiende Event
o CustomEvent
.
/** My custom event, which fires when needed */
export interface SomeEvent extends CustomEvent {
detail: {
/** Property inside event.detail */
myCustomProp: string;
};
}
Cualquier valor establecido directamente en la declaración de propiedad se utilizará como el valor predeterminado. Cualquier valor no primitivo (matriz, objeto, etc.) se envolverá con una función:
export class MyElement {
title : string = '' ;
categories : Array = [ ] ;
}
se traducirá a
Polymer ( {
properties : {
title : {
type : string ,
value : ''
} ,
categories : {
type : Array ,
value : function ( ) {
return [ ] ;
}
}
}
} ) ;
No todo debe agregarse a properties
de configuración. Para omitir ese proceso, la propiedad debe definirse como privada:
export class MyElement {
name : string ; // is added to properties config
private hasName : boolean ; // is NOT added to properties config
}
No todo en Polymer se puede hacer con palabras clave TypeScript, pero la propiedad de solo lectura es tan fácil como prefijarlo readonly
:
export class MyElement {
readonly name : string ; // property will have `readOnly` flag
}
ES Mixins se admiten desde TypeScript 2.2. Puedes leer más sobre ellos aquí.
Las mezclas no son compatibles con el polímero V1
Los comportamientos son el primer enfoque para compartir la funcionalidad en el polímero (ahora reemplazado por ES Mixins). Se definen como objetos simples con propiedades y métodos de polímeros enumerados al igual que con el objeto de configuración de polímero V1. Para agregar un comportamiento, use el Polymer.mixinBehaviors()
mixin (más información aquí). Para el polímero V1, se agregarán a la configuración de comportamientos, mientras que el polímero V2 los usará con la mezcla anterior.
Como se mencionó anteriormente, no todo se puede hacer con palabras clave. Es por eso que TWC viene con un conjunto de anotaciones de tiempo de diseño.
Para usarlos, instale TWC localmente e importe en los archivos de origen de los elementos según sea necesario:
import { attr , compute , notify , observe , style , template } from 'twc/polymer' ;
Para darle a su componente un cuerpo, debe proporcionarle una plantilla. Esto se realiza utilizando la anotación @template
, que acepta el código de plantilla HTML o una ruta a la plantilla HTML (tiene que tener la extensión .html
).
@ template ( `<h1>Hello {{name}}</h1>` )
export class MyElement {
name : string ;
}
@ template ( `template.html` )
export class MyElement {
name : string ;
}
El estilo del componente es tan fácil como darle una plantilla. @style
Annotation acepta código CSS, ruta del archivo CSS o nombre de estilo compartido. Se pueden proporcionar múltiples estilos a un solo componente.
@ template ( `<h1>Hello {{name}}</h1>` )
@ style ( `:host {display: block;}` , `style.css` , `shared-styles` )
export class MyElement {
name : string ;
}
@attr
y @notify
Agregar reflectToAttribute
y notify
los indicadores a la configuración properties
.
export class MyElement {
@ attr ( ) name : string ; // property will have `reflectToAttribute` flag
@ notify ( ) age : number ; // property will have `notify` flag
}
Las propiedades calculadas son propiedades que combinan una o más dependencias (propiedades observadas). Siempre que cualquiera de los cambios de dependencia, el método de propiedad calculada se asigne a la propiedad. Más información aquí. TWC permite crearlos de 2 maneras: proporcionando una matriz de nombre y dependencias de la función, o al pasar una función de resolución directamente (en ese caso, las dependencias se pueden pasar en una matriz de cadenas, o como argumentos de función).
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` ;
}
}
Puede reaccionar a cualquier propiedad o cambio de ruta no solo por propiedades calculadas, sino también por observadores. Observador no devuelve nada y esta es la única diferencia entre ellos.
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` ;
}
}
Los componentes web escritos están en una fase temprana y necesita sus comentarios. Pruébelo y si encuentra un problema, publíquelo en problemas. Además, ¡no dudes en publicar también ideas!
classList
) Para ejecutar pruebas en Windows ( npm run test
) es actualmente necesario modificar la sección de include
del archivo tsconfig.json
para que contenga el patrón a continuación:
{
"include" : [
" node_modules/@types/**/*.d.ts "
]
}