Uma biblioteca Virtual DOM, com foco na simplicidade, modularidade, recursos poderosos e desempenho.
Agradecemos ao BrowSerstack por fornecer acesso às suas ótimas ferramentas de teste de navegador cruzado.
Inglês | 简体中文 | hindi
Virtual Dom é incrível. Ele nos permite expressar a visão de nosso aplicativo em função de seu estado. Mas as soluções existentes eram muito inchadas, muito lentas, com falta de características, tinham uma API tendenciosa em direção a OOP e/ou com os recursos que eu precisava.
O Snabbdom consiste em um núcleo extremamente simples, performente e extensível, que é apenas ± 200 SLOC. Oferece uma arquitetura modular com funcionalidade rica para extensões por meio de módulos personalizados. Para manter o núcleo simples, toda a funcionalidade não essencial é delegada a módulos.
Você pode moldar o Snabbdom no que quiser! Escolha, escolha e personalize a funcionalidade desejada. Como alternativa, você pode usar as extensões padrão e obter uma biblioteca Virtual DOM com alto desempenho, tamanho pequeno e todos os recursos listados abaixo.
h Função para criar facilmente nós DOM virtuais.h import {
init ,
classModule ,
propsModule ,
styleModule ,
eventListenersModule ,
h
} from "snabbdom" ;
const patch = init ( [
// Init patch function with chosen modules
classModule , // makes it easy to toggle classes
propsModule , // for setting properties on DOM elements
styleModule , // handles styling on elements with support for animations
eventListenersModule // attaches event listeners
] ) ;
const container = document . getElementById ( "container" ) ;
const vnode = h (
"div#container.two.classes" ,
{ on : { click : ( ) => console . log ( "div clicked" ) } } ,
[
h ( "span" , { style : { fontWeight : "bold" } } , "This is bold" ) ,
" and this is just normal text" ,
h ( "a" , { props : { href : "/foo" } } , "I'll take you places!" )
]
) ;
// Patch into empty DOM element – this modifies the DOM as a side effect
patch ( container , vnode ) ;
const newVnode = h (
"div#container.two.classes" ,
{ on : { click : ( ) => console . log ( "updated div clicked" ) } } ,
[
h (
"span" ,
{ style : { fontWeight : "normal" , fontStyle : "italic" } } ,
"This is now italic type"
) ,
" and this is still just normal text" ,
h ( "a" , { props : { href : "/bar" } } , "I'll take you places!" )
]
) ;
// Second `patch` invocation
patch ( vnode , newVnode ) ; // Snabbdom efficiently updates the old view to the new state initpatchhfragment (experimental)toVNodeinitinsertremovedestroyremovedestroyO núcleo do Snabbdom fornece apenas a funcionalidade mais essencial. Ele foi projetado para ser o mais simples possível enquanto ainda é rápido e extensível.
init O núcleo expõe apenas uma única função init . Este init pega uma lista de módulos e retorna uma função patch que usa o conjunto especificado de módulos.
import { classModule , styleModule } from "snabbdom" ;
const patch = init ( [ classModule , styleModule ] ) ;patch A função patch retornada pelo init recebe dois argumentos. O primeiro é um elemento DOM ou um VNode que representa a visualização atual. O segundo é um vnode que representa a nova visualização atualizada.
Se um elemento DOM com um pai for passado, newVnode será transformado em um nó DOM e o elemento passado será substituído pelo nó DOM criado. Se um vnode antigo for passado, o Snabbdom o modificará com eficiência para corresponder à descrição no novo VNode.
Qualquer vnode antigo aprovado deve ser o vNode resultante de uma chamada anterior para patch . Isso é necessário, pois o Snabbdom armazena informações no vnode. Isso torna possível implementar uma arquitetura mais simples e mais performante. Isso também evita a criação de uma nova antiga árvore vnode.
patch ( oldVnode , newVnode ) ; Embora não haja API especificamente para remover uma árvore vnode de seu elemento de ponto de montagem, uma maneira de quase conseguir isso está fornecendo um comentário como o segundo argumento a patch , como:
patch (
oldVnode ,
h ( "!" , {
hooks : {
post : ( ) => {
/* patch complete */
}
}
} )
) ;Obviamente, ainda há um único nó de comentário no ponto de montagem.
h Recomenda -se que você use h para criar vnodes. Ele aceita uma tag/seletor como uma string, um objeto de dados opcional e uma string opcional ou uma matriz de crianças.
import { h } from "snabbdom" ;
const vnode = h ( "div#container" , { style : { color : "#000" } } , [
h ( "h1.primary-title" , "Headline" ) ,
h ( "p" , "A paragraph" )
] ) ;fragment (experimental)CUIDADO: Esse recurso é atualmente experimental e deve ser optado. Sua API pode ser alterada sem um grande aumento na versão.
const patch = init ( modules , undefined , {
experimental : {
fragments : true
}
} ) ;Cria um nó virtual que será convertido em um fragmento de documentos que contém as crianças dadas.
import { fragment , h } from "snabbdom" ;
const vnode = fragment ( [ "I am" , h ( "span" , [ " a" , " fragment" ] ) ] ) ;toVNodeConverte um nó DOM em um nó virtual. Especialmente bom para corrigir o conteúdo HTML gerado por servidor pré-existente.
import {
init ,
styleModule ,
attributesModule ,
h ,
toVNode
} from "snabbdom" ;
const patch = init ( [
// Initialize a `patch` function with the modules used by `toVNode`
attributesModule // handles attributes from the DOM node
datasetModule , // handles `data-*` attributes from the DOM node
] ) ;
const newVNode = h ( "div" , { style : { color : "#000" } } , [
h ( "h1" , "Headline" ) ,
h ( "p" , "A paragraph" ) ,
h ( "img" , { attrs : { src : "sunrise.png" , alt : "morning sunrise" } } )
] ) ;
patch ( toVNode ( document . querySelector ( ".container" ) ) , newVNode ) ;Os ganchos são uma maneira de prender o ciclo de vida dos nós DOM. O Snabbdom oferece uma rica seleção de ganchos. Os ganchos são usados por módulos para estender o snabbdom e no código normal para executar o código arbitrário nos pontos desejados na vida de um nó virtual.
| Nome | Acionado quando | Argumentos para retorno de chamada |
|---|---|---|
pre | O processo de patch começa | nenhum |
init | Um vnode foi adicionado | vnode |
create | Um elemento DOM foi criado com base em um vnode | emptyVnode, vnode |
insert | Um elemento foi inserido no DOM | vnode |
prepatch | Um elemento está prestes a ser corrigido | oldVnode, vnode |
update | Um elemento está sendo atualizado | oldVnode, vnode |
postpatch | Um elemento foi corrigido | oldVnode, vnode |
destroy | um elemento está sendo removido direta ou indiretamente | vnode |
remove | um elemento está sendo removido diretamente do DOM | vnode, removeCallback |
post | O processo de patch é feito | nenhum |
Os ganchos a seguir estão disponíveis para módulos: pre , create , update , destroy , remove , post .
Os ganchos a seguir estão disponíveis na propriedade hook de elementos individuais: init , create , insert , prepatch , update , postpatch , destroy , remove .
Para usar ganchos, passe -os como um objeto para hook o campo do argumento do objeto de dados.
h ( "div.row" , {
key : movie . rank ,
hook : {
insert : ( vnode ) => {
movie . elmHeight = vnode . elm . offsetHeight ;
}
}
} ) ; initEste gancho é chamado durante o processo de patch quando um novo nó virtual foi encontrado. O gancho é chamado antes que o Snabbdom tenha processado o nó de qualquer maneira. Ou seja, antes de criar um nó DOM com base no vNode.
insertEste gancho é chamado quando o elemento DOM para um vNode foi inserido no documento e o restante do ciclo do patch é feito. Isso significa que você pode fazer medições DOM (como usar o GetBoundingClientRect neste gancho com segurança, sabendo que nenhum elemento será alterado posteriormente, isso pode afetar a posição dos elementos inseridos.
remove Permite que você se conecte na remoção de um elemento. O gancho é chamado quando um vnode deve ser removido do DOM. A função de manuseio recebe o VNODE e um retorno de chamada. Você pode controlar e atrasar a remoção com o retorno de chamada. O retorno de chamada deve ser chamado assim que o gancho for feito fazendo seus negócios, e o elemento só será removido assim que todos os ganchos remove invocarem seu retorno de chamada.
O gancho é acionado apenas quando um elemento deve ser removido de seus pais - não se for o filho de um elemento que for removido. Para isso, veja o gancho destroy .
destroyEste gancho é invocado em um nó virtual quando seu elemento DOM é removido do DOM ou se seu pai estiver sendo removido do DOM.
Para ver a diferença entre esse gancho e o gancho remove , considere um exemplo.
const vnode1 = h ( "div" , [ h ( "div" , [ h ( "span" , "Hello" ) ] ) ] ) ;
const vnode2 = h ( "div" , [ ] ) ;
patch ( container , vnode1 ) ;
patch ( vnode1 , vnode2 ) ; Aqui, destroy é acionada para o elemento div e o elemento span que ele contém. remove , por outro lado, é acionado apenas no elemento div porque é o único elemento que está sendo destacado de seus pais.
Você pode, por exemplo, usar remove para acionar uma animação quando um elemento está sendo removido e usar o gancho destroy para animar adicionalmente o desaparecimento dos filhos do elemento removido.
Os módulos funcionam registrando os ouvintes globais para obter ganchos. Um módulo é simplesmente um nomes de gancho de mapeamento de dicionário para funções.
const myModule = {
create : ( oldVnode , vnode ) => {
// invoked whenever a new virtual node is created
} ,
update : ( oldVnode , vnode ) => {
// invoked whenever a virtual node is updated
}
} ;Com esse mecanismo, você pode aumentar facilmente o comportamento do Snabbdom. Para demonstração, dê uma olhada nas implementações dos módulos padrão.
Isso descreve os módulos principais. Todos os módulos são opcionais. Os exemplos da JSX assumem que você está usando o jsx Pragma fornecido por esta biblioteca.
O módulo de classe fornece uma maneira fácil de alternar dinamicamente as classes nos elementos. Ele espera um objeto na propriedade de dados class . O objeto deve mapear nomes de classe para booleanos que indiquem se a classe deve ou não ficar ou ir no vnode.
h ( "a" , { class : { active : true , selected : false } } , "Toggle" ) ; Na JSX, você pode usar class como esta:
< div class = { { foo : true , bar : true } } />
// Renders as: <div class="foo bar"></div>Permite definir propriedades nos elementos DOM.
h ( "a" , { props : { href : "/foo" } } , "Go to Foo" ) ; Na JSX, você pode usar props como este:
< input props = { { name : "foo" } } />
// Renders as: <input name="foo" /> with input.name === "foo"As propriedades só podem ser definidas. Não removido. Embora os navegadores permitam adição e exclusão de propriedades personalizadas, a exclusão não será tentada por este módulo. Isso faz sentido, porque as propriedades nativas do DOM não podem ser removidas. E se você estiver usando propriedades personalizadas para armazenar valores ou referenciar objetos no DOM, considere usar os atributos de dados. Talvez através do módulo do conjunto de dados.
O mesmo que os adereços, mas defina atributos em vez de propriedades nos elementos DOM.
h ( "a" , { attrs : { href : "/foo" } } , "Go to Foo" ) ; Na JSX, você pode usar attrs como este:
< div attrs = { { "aria-label" : "I'm a div" } } />
// Renders as: <div aria-label="I'm a div"></div> Os atributos são adicionados e atualizados usando setAttribute . No caso de um atributo que foi adicionado/conjunto anteriormente e não está mais presente no objeto attrs , ele é removido da lista de atributos do elemento DOM usando removeAttribute .
No caso de atributos booleanos (por exemplo, disabled , hidden , selected ...), o significado não depende do valor do atributo ( true ou false ), mas depende da presença/ausência do próprio atributo no elemento DOM. Esses atributos são tratados de maneira diferente pelo módulo: se um atributo booleano for definido como um valor falsamente ( 0 , -0 , null , false , NaN , undefined ou a string vazia ( "" )), o atributo será removido da lista de atributos do elemento dom.
Permite definir atributos de dados personalizados ( data-* ) nos elementos DOM. Estes podem ser acessados com a propriedade HTMLELEMENT.Dataset.
h ( "button" , { dataset : { action : "reset" } } , "Reset" ) ; Na JSX, você pode usar dataset como este:
< div dataset = { { foo : "bar" } } />
// Renders as: <div data-foo="bar"></div>O módulo de estilo é para fazer com que seu HTML pareça liso e anime sem problemas. Na sua essência, ele permite definir propriedades CSS em elementos.
h (
"span" ,
{
style : {
border : "1px solid #bada55" ,
color : "#c0ffee" ,
fontWeight : "bold"
}
} ,
"Say my name, and every colour illuminates"
) ; Na JSX, você pode usar style assim:
< div
style = { {
border : "1px solid #bada55" ,
color : "#c0ffee" ,
fontWeight : "bold"
} }
/>
// Renders as: <div style="border: 1px solid #bada55; color: #c0ffee; font-weight: bold"></div> As propriedades personalizadas do CSS (também conhecidas como variáveis CSS) são suportadas, elas devem ser prefixadas com --
h (
"div" ,
{
style : { "--warnColor" : "yellow" }
} ,
"Warning"
) ; Você pode especificar as propriedades como atrasadas. Sempre que essas propriedades mudam, a alteração não é aplicada até depois do próximo quadro.
h (
"span" ,
{
style : {
opacity : "0" ,
transition : "opacity 1s" ,
delayed : { opacity : "1" }
}
} ,
"Imma fade right in!"
) ;Isso facilita o fato de animar a entrada de elementos.
O valor all da transition-property não é suportado.
remove Os estilos definidos na propriedade remove entrarão em vigor assim que o elemento estiver prestes a ser removido do DOM. Os estilos aplicados devem ser animados com transições CSS. Somente quando todos os estilos forem feitos animando, o elemento será removido do DOM.
h (
"span" ,
{
style : {
opacity : "1" ,
transition : "opacity 1s" ,
remove : { opacity : "0" }
}
} ,
"It's better to fade out than to burn away"
) ;Isso facilita o fato de animar a remoção de elementos.
O valor all da transition-property não é suportado.
destroy h (
"span" ,
{
style : {
opacity : "1" ,
transition : "opacity 1s" ,
destroy : { opacity : "0" }
}
} ,
"It's better to fade out than to burn away"
) ; O valor all da transition-property não é suportado.
O módulo de ouvintes do evento fornece recursos poderosos para anexar ouvintes de eventos.
Você pode anexar uma função a um evento em um vnode fornecendo um objeto on uma propriedade correspondente ao nome do evento que deseja ouvir. A função será chamada quando o evento acontecer e será passado para o objeto de evento que pertence a ele.
function clickHandler ( ev ) {
console . log ( "got clicked" ) ;
}
h ( "div" , { on : { click : clickHandler } } ) ; Na JSX, você pode usar on :
< div on = { { click : clickHandler } } />O Snabbdom permite trocar os manipuladores de eventos entre renderizações. Isso acontece sem tocar os manipuladores de eventos anexados ao DOM.
Observe, no entanto, que você deve ter cuidado ao compartilhar manipuladores de eventos entre VNodes , devido à técnica que esse módulo usa para evitar re-vincular manipuladores de eventos ao DOM. (E, em geral, o compartilhamento de dados entre VNodes não é garantido para o trabalho, porque os módulos podem mudar os dados fornecidos).
Em particular, você não deve fazer algo assim:
// Does not work
const sharedHandler = {
change : ( e ) => {
console . log ( "you chose: " + e . target . value ) ;
}
} ;
h ( "div" , [
h ( "input" , {
props : { type : "radio" , name : "test" , value : "0" } ,
on : sharedHandler
} ) ,
h ( "input" , {
props : { type : "radio" , name : "test" , value : "1" } ,
on : sharedHandler
} ) ,
h ( "input" , {
props : { type : "radio" , name : "test" , value : "2" } ,
on : sharedHandler
} )
] ) ; Para muitos casos, você pode usar manipuladores baseados em matriz (descritos acima). Como alternativa, basta garantir que cada nó seja passado único on valores:
// Works
const sharedHandler = ( e ) => {
console . log ( "you chose: " + e . target . value ) ;
} ;
h ( "div" , [
h ( "input" , {
props : { type : "radio" , name : "test" , value : "0" } ,
on : { change : sharedHandler }
} ) ,
h ( "input" , {
props : { type : "radio" , name : "test" , value : "1" } ,
on : { change : sharedHandler }
} ) ,
h ( "input" , {
props : { type : "radio" , name : "test" , value : "2" } ,
on : { change : sharedHandler }
} )
] ) ; O SVG funciona apenas ao usar a função h para criar nós virtuais. Os elementos SVG são criados automaticamente com os espaços de nome apropriados.
const vnode = h ( "div" , [
h ( "svg" , { attrs : { width : 100 , height : 100 } } , [
h ( "circle" , {
attrs : {
cx : 50 ,
cy : 50 ,
r : 40 ,
stroke : "green" ,
"stroke-width" : 4 ,
fill : "yellow"
}
} )
] )
] ) ;Veja também o exemplo SVG e o exemplo de carrossel SVG.
Certos navegadores (como IE <= 11) não suportam a propriedade classList em elementos SVG. Como o módulo de classe usa internamente classList , ele não funcionará neste caso, a menos que você use um poli -preenchimento de classe. (Se você não deseja usar um poli -preenchimento, pode usar o atributo class com o módulo Atributos ).
A função thunk leva um seletor, uma chave para identificar um thunk, uma função que retorna um vNode e uma quantidade variável de parâmetros de estado. Se chamado, a função Renderizar receberá os argumentos do Estado.
thunk(selector, key, renderFn, [stateArguments])
O renderFn é chamado apenas se o renderFn for alterado ou [stateArguments] Comprimento da matriz ou seus elementos forem alterados.
A key é opcional. Deve ser fornecido quando o selector não for único entre os irmãos Thunks. Isso garante que o Thunk seja sempre correspondido corretamente ao diferenciar.
Os Thunks são uma estratégia de otimização que pode ser usada quando se lida com dados imutáveis.
Considere uma função simples para criar um nó virtual com base em um número.
function numberView ( n ) {
return h ( "div" , "Number is: " + n ) ;
} A visão depende apenas de n . Isso significa que, se n permanecer inalterado, criar o nó DOM virtual e corrigi -lo contra o antigo vnode é um desperdício. Para evitar a sobrecarga, podemos usar a função do ajudante thunk .
function render ( state ) {
return thunk ( "num" , numberView , [ state . number ] ) ;
} Em vez de realmente invocar a função numberView , isso colocará apenas um vnode dummy na árvore virtual. Quando o Snabbdom remente esse vnode fictício contra um vNode anterior, ele comparará o valor de n . Se n permanecer inalterado, ele simplesmente reutilizará o antigo vnode. Isso evita recriar a visualização do número e o processo diff.
A função de visualização aqui é apenas um exemplo. Na prática, os thunks só são relevantes se você estiver tornando uma visão complicada que leva um tempo computacional significativo para gerar.
Observe que os fragmentos JSX ainda são experimentais e devem ser optados. Veja a seção fragment para obter detalhes.
Adicione as seguintes opções ao seu tsconfig.json :
{
"compilerOptions" : {
"jsx" : " react " ,
"jsxFactory" : " jsx " ,
"jsxFragmentFactory" : " Fragment "
}
} Em seguida, certifique -se de usar a extensão do arquivo .tsx e importar a função jsx e a função Fragment na parte superior do arquivo:
import { Fragment , jsx , VNode } from "snabbdom" ;
const node : VNode = (
< div >
< span > I was created with JSX </ span >
</ div >
) ;
const fragment : VNode = (
< >
< span > JSX fragments </ span >
are experimentally supported
</ >
) ;Adicione as seguintes opções à sua configuração de Babel:
{
"plugins" : [
[
" @babel/plugin-transform-react-jsx " ,
{
"pragma" : " jsx " ,
"pragmaFrag" : " Fragment "
}
]
]
} Em seguida, importe a função jsx e a função Fragment na parte superior do arquivo:
import { Fragment , jsx } from "snabbdom" ;
const node = (
< div >
< span > I was created with JSX </ span >
</ div >
) ;
const fragment = (
< >
< span > JSX fragments </ span >
are experimentally supported
</ >
) ; Propriedades
A propriedade sel especifica o elemento HTML do vNode, opcionalmente, seu id prefixado por um # , e zero ou mais classes, cada uma prefixada por a . . A sintaxe é inspirada nos seletores CSS. Aqui estão alguns exemplos:
div#container.bar.baz - um elemento div com o container de identificação e a bar de classes e baz .li - um elemento li sem id nem aulas.button.alert.primary - elemento button com o alert de duas classes e primary . O seletor deve ser estático , ou seja, não deve mudar ao longo da vida útil do elemento. Para definir um id dinâmico, use o módulo Props e para definir classes dinâmicas, use o módulo de classe.
Como o seletor é estático, o Snabbdom o usa como parte de uma identidade VNODES. Por exemplo, se os dois filhos vnodes
[ h ( "div#container.padding" , children1 ) , h ( "div.padding" , children2 ) ] ;são remendados contra
[ h ( "div#container.padding" , children2 ) , h ( "div.padding" , children1 ) ] ;Em seguida, o Snabbdom usa o seletor para identificar os vnodes e reordená -los na árvore Dom em vez de criar um novo elemento DOM. Esse uso de seletores evita a necessidade de especificar chaves em muitos casos.
A propriedade .data de um nó virtual é o local para adicionar informações para módulos para acessar e manipular o elemento DOM real quando for criado; Adicione estilos, aulas de CSS, atributos, etc.
O objeto de dados é o segundo parâmetro (opcional) para h()
Por exemplo h('div', {props: {className: 'container'}}, [...]) produzirá um nó virtual com
( {
props : {
className : "container"
}
} ) ; como seu objeto .data .
A propriedade .children de um nó virtual é o terceiro parâmetro (opcional) de h() durante a criação. .children é simplesmente uma variedade de nós virtuais que devem ser adicionados como filhos do Nó DOM dos pais após a criação.
Por exemplo h('div', {}, [ h('h1', {}, 'Hello, World') ]) criará um nó virtual com
[
{
sel : "h1" ,
data : { } ,
children : undefined ,
text : "Hello, World" ,
elm : Element ,
key : undefined
}
] ; como sua .children .
A propriedade .text é criada quando um nó virtual é criado com apenas uma única criança que possui texto e requer apenas document.createTextNode() a ser usada.
Por exemplo: h('h1', {}, 'Hello') criará um nó virtual com Hello como sua propriedade .text .
A propriedade .elm de um nó virtual é um ponteiro para o nó DOM real criado pelo snabbdom. Esta propriedade é muito útil para fazer cálculos em ganchos e módulos.
A propriedade .key é criada quando uma chave é fornecida dentro do seu objeto .data . A propriedade .key é usada para manter os indicadores dos nós que existiam anteriormente para evitar recriá -los se for desnecessário. Isso é muito útil para coisas como reordenação de lista. Uma chave deve ser uma string ou um número para permitir a pesquisa adequada, pois é armazenada internamente como um par de chave/valor dentro de um objeto, onde .key é a chave e o valor é a propriedade .elm criada.
Se fornecido, a propriedade .key deve ser única entre os elementos irmãos.
Por exemplo: h('div', {key: 1}, []) criará um objeto de nó virtual com uma propriedade .key com o valor de 1 .
O Snabbdom é uma biblioteca Virtual DOM de baixo nível. É poucopinado com relação a como você deve estruturar seu aplicativo.
Aqui estão algumas abordagens para criar aplicações com Snabbdom.
Certifique -se de compartilhá -lo se estiver criando um aplicativo de outra maneira usando o Snabbdom.
Os pacotes relacionados ao Snabbdom devem ser marcados com a palavra -chave snabbdom e publicados no NPM. Eles podem ser encontrados usando as keywords:snabbdom .
Uncaught NotFoundError: Failed to execute 'insertBefore' on 'Node':
The node before which the new node is to be inserted is not a child of this node.
O motivo desse erro é a reutilização de vnodes entre os patches (consulte o exemplo de código), o Snabbdom armazena nós DOM reais dentro dos nós virtuais de DOM passados como melhoria de desempenho, portanto, a reutilização dos nós entre os patches não é suportada.
const sharedNode = h ( "div" , { } , "Selected" ) ;
const vnode1 = h ( "div" , [
h ( "div" , { } , [ "One" ] ) ,
h ( "div" , { } , [ "Two" ] ) ,
h ( "div" , { } , [ sharedNode ] )
] ) ;
const vnode2 = h ( "div" , [
h ( "div" , { } , [ "One" ] ) ,
h ( "div" , { } , [ sharedNode ] ) ,
h ( "div" , { } , [ "Three" ] )
] ) ;
patch ( container , vnode1 ) ;
patch ( vnode1 , vnode2 ) ;Você pode corrigir esse problema criando uma cópia superficial do objeto (aqui com sintaxe de spread de objeto):
const vnode2 = h ( "div" , [
h ( "div" , { } , [ "One" ] ) ,
h ( "div" , { } , [ { ... sharedNode } ] ) ,
h ( "div" , { } , [ "Three" ] )
] ) ;Outra solução seria envolver os vnodes compartilhados em uma função de fábrica:
const sharedNode = ( ) => h ( "div" , { } , "Selected" ) ;
const vnode1 = h ( "div" , [
h ( "div" , { } , [ "One" ] ) ,
h ( "div" , { } , [ "Two" ] ) ,
h ( "div" , { } , [ sharedNode ( ) ] )
] ) ; Os pedidos de puxar que a comunidade possam se importar para fornecer feedback devem ser mesclados após a fornecimento dessa oportunidade de alguns dias.