Construa componentes da interface do usuário com o HTML que você já possui.
2KB Gzipped e 6kb Minified! ?
data em seu html existente < div data-component =" Counter " >
< p data-bind =" state:Counter.count " > 0 </ p >
< button data-action =" click->Counter.decrement " >
-1
</ button >
< button data-action =" click->Counter.increment " >
+1
</ button >
</ div >class JavaScript? import { Component } from "domponent" ;
export default class Counter extends Component {
constructor ( el ) {
super ( el ) ;
}
increment ( ) {
this . setState ( { count : this . state . count + 1 } ) ;
}
decrement ( ) {
this . setState ( { count : this . state . count - 1 } ) ;
}
} import { Init } from "domponent" ;
import Counter from "./Counter.js" ;
const config = {
selector : document . getElementById ( "root" ) ,
components : {
Counter
} ,
appCreated : callbackFunction
} ;
new Init ( config ) ;E você está pronto para ir !!
Esta biblioteca configura uma maneira limpa e moderna de transformar o HTML pré -render em componentes da interface do usuário. Você pode implementar facilmente algum pouco de ligação a dados, lidar com o escopo, passar dados e criar componentes usando algumas das convenções neste script. É para ser uma alternativa muito leve para os estímulos com um sabor de reação (métodos de ciclo de vida, adereços e estado de componentes).
O Domponent não lida com a renderização do lado do cliente fora da caixa, não cria DOM virtual, não é diferenciado (embora faça o estado e os adereços diff). Não é para lidar com o roteamento ou todo o estado de aplicação. Destina -se a tomar fragmentos HTML (Thymeleaf, trilhos, pug, qualquer mecanismo de modelo que você usar) e criar funcionalidade reutilizável na forma de componentes.
Domponente é semelhante ao nocaute de algumas maneiras:
Ao contrário dos knockoutjs, Domponent:
Suprimir
Html
< p > First name: < input data-bind =" value: firstName " /> </ p >
< p > Last name: < input data-bind =" value: lastName " /> </ p >
< h2 > Hello, < span data-bind =" text: fullName " > </ span > ! </ h2 >JS
var ViewModel = function ( first , last ) {
this . firstName = ko . observable ( first ) ;
this . lastName = ko . observable ( last ) ;
this . fullName = ko . pureComputed ( function ( ) {
return ` ${ this . firstName ( ) } ${ this . lastName ( ) } ` ;
} , this ) ;
} ;
ko . applyBindings ( new ViewModel ( "Planet" , "Earth" ) ) ;Domponente
Html
< div data-component =" Hello " data-state =" { " firstName ": "Planet", "lastName": "Earth"}" >
< p > First name: < input data-action =" input->Hello.setFirstName " /> </ p >
< p > Last name: < input data-action =" input->Hello.setLastName " /> </ p >
< h2 > Hello, < span data-bind =" state:Hello.fullName " > </ span > ! </ h2 >
</ div >JS
import { Component } from "domponent" ;
export default class Hello extends Component {
constructor ( conf ) {
super ( conf ) ;
}
setFirstName ( event ) {
this . setState ( { firstName : event . target . value } , ( ) => {
this . setFullName ( ) ;
} ) ;
}
setLastName ( event ) {
this . setState ( { lastName : event . target . value } , ( ) => {
this . setFullName ( ) ;
} ) ;
}
setFullName ( ) {
this . setState ( {
fullName : ` ${ this . state . firstName } ${ this . state . lastName } `
} ) ;
}
}https://tamb.github.io/domponent/
LISTA TODO: https://codesandbox.io/embed/domponent-todo-with-undo-redo-sp3s2?fontsize=14
Demoção local
git clone este reponpm installnpm run build:html-dev ou npm run build:html-prod npm install -- save domponent Você pode usar uma versão ES5 importando este arquivo domponent/dist/domponent.es5.production.min.js
Se você não está usando um transpiler, é recomendável usar o ES5 UMD. Então, aqui está o link JSDELVR:
// production
< script type = "text/javascript" src = "https://cdn.jsdelivr.net/npm/domponent@VERSION/dist/domponent.es5.production.min.js" defer > </ script >
// development
< script type = "text/javascript" src = "https://cdn.jsdelivr.net/npm/domponent@VERSION/dist/domponent.es5.development.min.js" defer > < / script > NOTA: Use o máximo ou o pouco dessa biblioteca que quiser. Você pode usar isso apenas atributos data-component , data-ref e ref data-ref-array e facilitar a seleção do DOM. Você pode fazer componentes sem estado com a classe de Exponent . O céu é o limite. Na sua essência, o Domponent é um conjunto de classes de utilitário para o seu HTML.
data-component Usamos este garoto mau para combinar com o nome do componente com sua class correspondente no objeto de configuração Init
Exemplo: se o seu html for data-component="Counter" | você deve ter um componente em sua configuração chamada Counter
data-bind Liga state ou props ao textContent de um elemento primeiro, você especifica se deseja vincular state ou props data-bind="state:Counter.count" ou data-bind="props:Counter.count" A metade esquerda do : diz ao componente o que se liga a (Estado ou adereços), a metade direita diz ao componente que dentro do estado ou de que se vincule a (estado ou adereços), a chave direita para o componente ou a chave para o componente ou o estado ou os prontos para lidar com (estado ou adereços), a chave direita para o componente ou a chave para o componente ou o estado de lidar com (Estado ou Props), a chave para o componente ou a chave para o que se lida (Estado ou Props).
data-actionLigna um evento DOM com um método de componente. Considere o seguinte:
< button data-action =" click->Counter.increment " >
+1
</ button > A metade esquerda do : representa a corda literal para o evento DOM ouvir. A metade direita corresponde ao método do componente
Nota: Você pode adicionar vários ouvintes com um tubo | exemplo:
< button data-action =" click->Counter.increment|mouseover->Counter.anotherMethod " >
+1
</ button > Você pode passar as opções eventListener também. As opções devem ser depois de um . Após o método da classe. As opções devem ser separadas por uma vírgula , .
< button
data-action =" click->Counter.increment.passive,capture|mouseover->Counter.anotherMethod.once,passive "
>
+1
</ button > data-state Se você deseja instanciar seu componente com um estado específico na memória , você deve anexar um atributo data-state ao elemento raiz do exemplo do componente:
<div data-component="Counter" data-state='{"count":24, "isEven": true}'>
...
</div>
Isso mesmo. data-state pega qualquer objeto JSON válido.
data-ref Se você precisar fazer referência a elementos DOM, você pode usar data-ref como assim:
< div data-ref =" Counter.myElement " > </ div > Você precisa prefácio em qual componente o elemento está. Em seguida, é armazenado no objeto de componentes $refs .
Você pode acessar o elemento no Counter usando this.$refs.myElement na instância do componente.
data-ref-arrayVocê pode criar uma variedade de elementos em seu componente desta maneira:
< div data-ref-array =" Counter.elements " > </ div >
< div data-ref-array =" Counter.elements " > </ div > Em seguida, é armazenado no objeto de componentes $refs . Você pode acessar a matriz de elementos em seu componente com this.$refs.elements .
data-key Isso é totalmente opcional. É uma string exclusiva para cada instância do componente.
Isso é usado internamente para vincular adereços. Portanto, você deve conhecer a $key do componente do qual está recebendo adereços.
< div data-component =" Counter " data-key =" aUniqueKey " >
...
</ div >Digamos que você esteja voando sobre isso em sua linguagem de modelos. Você deve garantir que suas chaves sejam únicas.
# for (let i=0; i < 10 ; i++){
< div data-component =" Counter " key =" `aUniqueKey${i}` " > ... </ div >
} Se você não usar esse atributo, uma chave exclusiva será atribuída a cada instância do componente automaticamente. Pode ser acessado por meio this.$key
data-props Você pode compartilhar o estado de um componente pai como props em um componente filho. A marcação seria assim
< div data-component =" Counter " key =" parentCounter " >
< div
data-props =" myAwesomeProp<-parentCounter:ofFive "
data-component =" DisplayAnything "
> </ div >
</ div > O lado esquerdo da seta <- é o nome do suporte no componente DisplayAnything . O lado direito da seta é $key do componente pai, um cólon : e o nome da peça de state para herdar.
Em seguida, você pode usar os métodos do ciclo de vida propsWillUpdate e propsDidUpdate para fazer alterações no componente filho.
Component ?Vamos continuar com o balcão. O JS mínimo necessário para criar um componente está abaixo:
class Counter extends Component {
constructor ( conf ) {
super ( conf ) ;
}
} super adiciona os métodos e propriedades básicas que seu componente precisa.
Não se mova diretamente o estado. Chame this.setState
setState ( stateObject , callbackFunction ) ;Isso é semelhante em conceito ao SetState da React - embora seja implementado de maneira diferente.
Você pode adicionar estados padrão ao seu componente JS e substituí -los no DOM
export default class Counter extends Component {
constructor ( conf ) {
super ( conf ) ;
this . state = {
count : parseInt ( this . state . count ) || 0 ,
isEven : this . state . count
? this . state . count % 2 === 0
? true
: false
: true ,
stateFieldFromDOM : this . state . stateFieldFromDOM || "default cat" ,
stateFieldDefault : "default iPhone 11"
} ;
this . setState ( this . state ) ;
} <div data-component="Counter" data-state="{"count": 4, "isEven":true, "stateFieldFromDOM": "some value here"}"
Os campos estaduais acima substituirão os campos estaduais JS padrão.
A ligação de valor do setState sempre será o textContent . Se você deseja usar o estado/adereços para renderizar HTML, pode adicionar um observador para esse valor e atualizar o nó $refs que abrigará o novo HTML.
watch ( ) {
return {
count : {
post ( newCount ) {
this . $refs . exclaimCount . innerHTML = `<div class="uppercase"> ${ newcount } !</div>` ;
}
}
}
}A seguir, são apresentados métodos que você pode usar para acessar componentes em vários pontos do seu ciclo de vida
| Método do ciclo de vida | Contexto | Descrição |
|---|---|---|
| conectando | Componente/expoente | Antes que a biblioteca se encaixe em qualquer um dos seus componentes/expoentes e você terá acesso a outros métodos |
| conectado | Componente/expoente | Depois que seu componente/expoente estiver conectado e todos os listadores de eventos estão no lugar |
| desconectando | Componente/expoente | Antes de remover o EventListenners e excluir o componente/expoente da memória |
| propswillupdate | Componente/expoente | Antes que os adereços sejam atualizados dentro do seu componente, nenhuma mutações dom |
| propsdidUpdate | Componente/expoente | Depois que os adereços foram atualizados e o DOM mudou |
| Statewillupdate | Componente | Antes que o estado do componente atual ou qualquer um dos adereços de seus dependentes mude |
| StatedIDUPDATE | Componente | Componentes infantis com adereços herdados fizeram suas manipulações de DOM e estado e adereços mudaram |
As classes Component e Exponent têm um método watch que deve retornar um objeto. Os observadores permitem que você se conecte em alterações específicas de valor state ou props durante o componente LifeCyle. Isso permite que sua lógica de estado seja isolada em vez de agrupar tudo com stateWillUpdate , stateDidUpdate , propsWillUpdate ou propsDidUpdate . Isso pretende imitar os observadores de perto em Vue.JS NOTA : Não nomeie seu state e props os campos da mesma forma. Isso é uma prática ruim e quebrará os observadores.
watch ( ) {
return {
myField : {
pre ( newValue , oldValue ) {
// my logic
} ,
post ( newValue ) {
// my logic
}
}
}
} Você pode ver seus campos de estado assistidos no objeto de componentes $watchers .
Estenda a classe Exponent para criar um componente com apenas props isso é um pouco mais leve que um Component . Mais rápido para conectar e ocupar menos memória.
import { Exponent } from 'domponent'
class StatelessThing extends Exponent{
constructor(conf){
super(conf);
}
}
Você só terá acesso a:
propsWillUpdatepropsDidUpdate Por que Exponent ??
Porque simplesmente interpreta ou expõe os dados que são fornecidos ... e parece componente.
Componentes ou expoentes receberão os seguintes campos.
| Nome do campo | Tipo | Acesso | Contexto | Descrição |
|---|---|---|---|---|
| $ app | objeto | público | Componente/expoente | Todo o aplicativo de domínio |
| $ b | variedade | privado | Componente/expoente | EventListener Lindings para uso interno |
| $ d | objeto | privado | Componente | Os componentes pais referenciam seus filhos |
| $ key | corda | público | Componente/expoente | Identificador exclusivo para a instância do componente |
| $ nome | corda | público | Componente/expoente | O nome do tipo de componente |
| $ p | objeto | privado | Componente/expoente | Coleção interna de adereços e suas referências DOM |
| adereços | objeto | público | Componente/expoente | Pares de chave/valor de dados passados |
| $ root | elemento | público | Componente/expoente | O nó raiz dom do componente |
| $ s | objeto | privado | Componente | Coleção interna de estado e suas referências DOM |
| estado | objeto | público | Componente | Pares de teclas/valores de dados que podem ser atualizados |
| $ observadores | objeto | público | Componente | Funções de mudança armazenadas e seu respectivo estado e chave de suporte |
Init ? Esta função cria o aplicativo e registra todos os componentes. Isso leva um objeto config conforme o argumento necessário:
const config = {
selector : document . getElementById ( "root" ) ,
components : { Counter } ,
appCreated : callbackFunction
} ;
const App = new Init ( config ) ;Em seguida, expõe os seguintes métodos:
E os seguintes objetos:
Você também pode excluir o objeto components da configuração e criar um aplicativo sem componentes para começar.
createComponent@params:
App . createComponent ( document . getElementById ( "added-html" ) , callback ) ; register@params
App . register ( NewComponent , callback ) ; deleteComponent@params:
data-key ou acessado com componente interno por meio this.$key App . deleteComponent ( "my-component-instance-key" , callback ) ; unregister@params:
App . unregister ( "NewComponent" , callback ) ; Para evitar atributos data- conflitantes com outros seletores, bibliotecas etc., você pode substituir os nomes de atributos padrão no objeto de configuração do aplicativo:
Init ( {
selector : getElementById ( 'root),
components : { Counter } ,
dataAttributes : {
component : 'mynamespace-component' ,
state : 'cool-state' ,
}
} ) ;Isso significa que seu HTML ficará assim:
< div data-mynamespace-component =" Counter " data-cool-state =' {"count":12} ' >
...
</ div >Opcionalmente, você pode personalizar a sintaxe que usa no seu HTML. Os seguintes itens podem ser personalizados.
INHERITS_FROM: '<-',
FROM_COMPONENT: '.',
KEY_VALUE: ':',
MULTIPLE_VALUES: "|",
METHOD_CALL: "->",
LIST: ","
Isso significa que em sua configuração você pode adicionar:
{
customSyntax : {
LIST : "!" ,
METHOD_CALL : "#"
}
}E seu HTML pode usar isso!
Ao desenvolver com o Domponent, o uso da construção de desenvolvimento adiciona erros e logs úteis ao seu console do desenvolvimento DOM (esse cara->)?
A maneira mais fácil de usar isso é com aliases do Webpack:
resolve : argv . mode === 'development' ? {
alias : {
domponent : 'domponent/dist/domponent.development.js'
}
} : { } ,Dessa forma, sua criação de desenvolvimento do Webpack trocará a versão de produção do Domponent para a versão aspersa com a ajuda da DOM.
Você pode escrever seu componente HTML para vários motores de modelos e incluí -los como parciais/fragmentos/qualquer que o seu mecanismo se referir como "pedaços de html".
Aqui estão alguns exemplos de como você pode usar o Domponent.
Nota: Apesar dessas diferenças de sintaxe na marcação, lembre -se de que o componente é simplesmente uma classe JS ✌️
Exemplo de sintaxe de pug ?
// counter.pug
mixin counter ( count )
div ( data - component = "Counter" data - state = `
{
"count": count,
"isEven": count % 2 === 0
}
` )
p ( data - bind = "state:Counter.count" ) # { count }
button ( data - action = "click->Counter.increment" ) + 1
button ( data - action = "click->Counter.decrement" ) - 1
// usage
+ counter ( 101119 )
+ counter ( 61316 )Exemplo de sintaxe tymeleaf ?
// counter.html
< div
data-component =" Counter "
th:fragment =" Counter "
th:data-state =' |{"count":${count}, "isEven": ${count % 2 == 0}}| '
>
< p data-bind =" state:Counter.count " th:text =" ${count} " > </ p >
< button data-action =" click->Counter.increment " >
+1
</ button >
< button data-action =" click->Counter.decrement " >
-1
</ button >
</ div >
// usage
< th:block th:replace =" ./counter.html :: Counter(count: 1289) " />
< th:block th:replace =" ./counter.html :: Counter(count: 491) " />Exemplo de sintaxe de barbear ⚔️ em breve ...
Exemplo de sintaxe do rubi nos trilhos ? em breve...
Exemplo de sintaxe do bigode ? em breve...
domponent [at] gmail [dot] com ( por favor, use o Domponent Support do assunto ou não responderemos )@domponent