Os componentes da web digitados trazem uma maneira baseada em diplometes e sem placa, para escrever módulos de polímero nativo (Polymer Toolbox Friendly). Todo o processo é feito no tempo de design, portanto, nenhuma dependência adicional precisa ser adicionada ao projeto.
npm install -g twc
TWC vem com a CLI. A maior parte de sua configuração vem do tsconfig
(e bower.json
), e praticamente funciona da mesma forma que o TSC. Para transformar as classes TS em módulos de polímeros nativos, basta inserir o Dir Root Project e executar o seguinte no terminal:
twc
Funciona exatamente como tsc
, lendo a configuração do arquivo tsconfig.json
. A única diferença é que produz arquivos .html
com módulo de polímero em vez de .js
simples.
As anotações estarão disponíveis no espaço de nome @types
NPM. Até que isso aconteça, os tipos precisam ser incluídos no tsconfig:
{
"compilerOptions": {
...
},
"files": [
...
],
"include": [
"node_modules/twc/types/polymer.decorators.d.ts"
]
}
O TWC permite compilar o mesmo código em polímero 1.x ou polímero 2.x. Antes de compilar, bower.json
é verificado quanto à versão de dependência do polímero e, em seguida, é usado como um destino. Por exemplo:
"polymer": "Polymer/polymer#^1.8.0"
construirá um módulo de polímero 1.x, enquanto este:
"polymer": "Polymer/polymer#^2.0.0"
Construa um módulo de polímero 2.x baseado em ES6.
As opções de compilador de texto TypeScript também estão disponíveis para o TWC, porém, nem tudo é suportado. Aqui está uma lista de opções não suportadas (pode eventualmente mudar no futuro):
Os módulos no TWC adotam a sintaxe e as palavras -chave do idioma TypeScript e são simplesmente apenas classes. As convenções a seguir correspondem ao Polymer 2.x (V1 Web Components Spec).
@ CustomElement ( )
export class MyElement extends Polymer . Element {
name : string ;
}
igual a
<dom-module id="my-element">
<script>
Polymer({
is: "my-element",
properties: {
name: {
type: String
}
}
});
</script>
</dom-module>
Existem 4 maneiras de adicionar um modelo (para que ninguém fique entediado):
@template
decorator@template
Decoratortemplate()
A primeira abordagem é muito comum e você provavelmente já viu isso várias vezes. Tudo o que normalmente passaria entre tags <template>
agora entrava no decorador. Sem mágica sofisticada aqui.
@ CustomElement ( )
@ template ( `<h1>Hello [[name]]</h1>` )
export class MyElement extends Polymer . Element {
name : string ;
}
Da mesma forma, a segunda abordagem, você só precisa fornecer um caminho relativo ao modelo (assim como você o importaria via <link rel="import">
tag). O conteúdo do arquivo de modelo deve ser como na primeira abordagem - código entre as tags <template>
.
@ CustomElement ( )
@ template ( 'template.html' )
export class MyElement extends Polymer . Element {
name : string ;
}
Se você estiver mais de um mundo do React, pode gostar do método render()
. Então, aqui está, um método template()
que funciona muito parecido. A vantagem desse método é que você tem acesso ao protótipo de classe e pode usá -lo em uma string de modelo. Toda this
será substituída por uma ligação bidirecional à propriedade (se você tiver uma sugestão de como determinar quando usar de mão dupla e quando usar a ligação unidirecional, informe-me).
@ CustomElement ( )
export class MyElement extends Polymer . Element {
name : string ;
template ( ) {
return `<h1>Hello ${ this . name } </h1>` ;
}
}
A abordagem final é deixar a classe como está e criar um arquivo de modelo, com o mesmo nome do arquivo TS. No tempo de compilação, o TWC pegará o conteúdo do arquivo e o anexará (assim como na segunda abordagem). Tenha cuidado! Se você não especificar o UPRIR, os módulos finais poderão substituir os modelos (por padrão, ele gerará arquivo HTML com o mesmo nome base).
Observe que o TWC usa modelos de polímero. Para ler mais sobre modelos e encadernação, consulte esses documentos.
As importações ES ainda não funcionam nos navegadores. Em vez disso, o Polymer usa as importações HTML. Isso nos permite usar tags <link>
para importar módulos, mas como fazemos isso no TWC?
import "./my-component.html";
O mesmo princípio se aplica a scripts (convertidos em tags <script>
):
import "./some-library.js";
Os acima são compilados para
<link rel="import" href="./my-component.html">
e
<script src="./some-library.js"></script>
respectivamente.
O manuseio de caminhos relativos aos repositórios de Bower ou NPM pode ser doloroso. É aqui que os aliases são úteis:
import "bower:polymer/polymer-element.html";
import "npm:jquery/dist/jquery.min.js";
O exposto acima será traduzido para usar o diretório Bower do .bowerrc
e voltará ao bower_components
. Como a maioria dos desenvolvedores usará polymer-cli
para atender aos componentes, os caminhos para bower_components
serão traduzidos como se a raiz do projeto estivesse dentro dessa pasta.
Se, por qualquer motivo, você precisar alterar os nomes ou caminhos de pastas NPM ou Bower, você poderá fazer isso definindo variáveis de ambiente bowerDir
e npmDir
.
Também é possível importar em relação à raiz do projeto. Basta adicionar um ~
na frente do caminho:
import "~demo/index.html";
import "~bower_components/polymer/polymer-element.html";
Para importar membros de outros módulos (por exemplo, importar um comportamento), use as importações ES:
import { IronControlState } from "bower:iron-behaviors/iron-control-state.html";
Se houver um espaço para nome declarado nas definições, ele atualizará automaticamente todas as instâncias do membro importado.
Observe que, para permitir a importação de módulos HTML, você precisa gerar definições.
Para gerar as declarações de tipo a partir de comportamentos/componentes existentes, use a ferramenta Potts. Basta instalá -lo globalmente ( npm install potts -g
) e executar potts
no diretório raiz do projeto. As declarações serão salvas no arquivo potts.d.ts
por padrão (configurável via --outFile
ou -o
sinalizador). Isso gerará declarações para todos os arquivos HTML ouça na seção main
do arquivo bower.json
de cada dependência do Bower. Todos os módulos serão declarados para corresponder ao caminho importável (por exemplo, bower:polymer/polymer.html
).
Todo projeto sólido deve ter uma documentação adequada. Isso também inclui a documentação de eventos disparados pelo componente. O TWC permite fazer isso com facilidade, criando uma interface que estende Event
ou CustomEvent
.
/** My custom event, which fires when needed */
export interface SomeEvent extends CustomEvent {
detail: {
/** Property inside event.detail */
myCustomProp: string;
};
}
Qualquer valor definido diretamente para a declaração de propriedade será usado como o valor padrão. Qualquer valor não primitivo (matriz, objeto etc.) será envolvido com uma função:
export class MyElement {
title : string = '' ;
categories : Array = [ ] ;
}
irá traduzir para
Polymer ( {
properties : {
title : {
type : string ,
value : ''
} ,
categories : {
type : Array ,
value : function ( ) {
return [ ] ;
}
}
}
} ) ;
Nem tudo deve ser adicionado à configuração properties
. Para pular esse processo, a propriedade deve ser definida como privada:
export class MyElement {
name : string ; // is added to properties config
private hasName : boolean ; // is NOT added to properties config
}
Nem tudo no Polymer pode ser feito com palavras -chave TypeScript, mas a propriedade somente leitura é tão fácil quanto prefixá -la readonly
:
export class MyElement {
readonly name : string ; // property will have `readOnly` flag
}
Os mixins ES são suportados desde o TypeScript 2.2. Você pode ler mais sobre eles aqui.
Mixins não são suportados pelo Polymer V1
Os comportamentos são a primeira abordagem para compartilhar a funcionalidade no polímero (agora substituído por Mixins ES). Eles são definidos como objetos simples com propriedades e métodos de polímero listados, assim como no objeto de configuração Polymer V1. Para adicionar um comportamento, use o mixin Polymer.mixinBehaviors()
(mais informações aqui). Para o Polymer V1, eles serão adicionados à configuração de comportamentos, enquanto o Polymer V2 os usará com Mixin acima.
Como mencionado anteriormente, nem tudo pode ser feito com palavras -chave. É por isso que o TWC vem com um conjunto de anotações em tempo de design.
Para usá -los, instale o TWC localmente e importe nos arquivos de origem dos elementos, conforme necessário:
import { attr , compute , notify , observe , style , template } from 'twc/polymer' ;
Para dar ao seu componente um corpo, você precisa fornecer um modelo. Isso é feito usando a anotação @template
, que aceita o código do modelo HTML ou um caminho para o modelo HTML (precisa ter uma extensão .html
).
@ template ( `<h1>Hello {{name}}</h1>` )
export class MyElement {
name : string ;
}
@ template ( `template.html` )
export class MyElement {
name : string ;
}
Estilizar o componente é tão fácil quanto dar um modelo. @style
anotação aceita código CSS, caminho do arquivo CSS ou nome de estilo compartilhado. Vários estilos podem ser fornecidos a um único componente.
@ template ( `<h1>Hello {{name}}</h1>` )
@ style ( `:host {display: block;}` , `style.css` , `shared-styles` )
export class MyElement {
name : string ;
}
@attr
e @notify
Add reflectToAttribute
e notify
os sinalizadores para properties
Config.
export class MyElement {
@ attr ( ) name : string ; // property will have `reflectToAttribute` flag
@ notify ( ) age : number ; // property will have `notify` flag
}
Propriedades calculadas são propriedades que combinam uma ou mais dependências (propriedades assistidas). Sempre que qualquer uma das alterações de dependência, o método de propriedade calculado dispara e o resultado retornado é atribuído à propriedade. Mais informações aqui. O TWC permite criá -los de duas maneiras: fornecendo um nome de nome e dependências de uma função, ou passando uma função de resolvedor diretamente (nesse caso, as dependências podem ser passadas em uma matriz de strings ou como argumentos de função).
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` ;
}
}
Você pode reagir a qualquer alteração de propriedade ou caminho não apenas por propriedades computadas, mas também pelos observadores. O observador não retorna nada e essa é a única diferença entre eles.
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` ;
}
}
Os componentes da web digitados estão em uma fase inicial e precisam de seus comentários. Por favor, experimente e se você encontrar um problema, publique -o em problemas. Além disso, não hesite em postar também idéias!
classList
) Para executar testes no Windows ( npm run test
), atualmente é necessário modificar a seção de include
o arquivo tsconfig.json
, para que ele contenha o padrão abaixo:
{
"include" : [
" node_modules/@types/**/*.d.ts "
]
}