A Função h no Vue.js e a Criação de Virtual DOM

O Virtual DOM é uma representação JavaScript da estrutura DOM real. Trata-se de um objeto simples contendo três propriedades essenciais: tag, props e children.

Considere o seguinte trecho HTML:

<section id="container">
  <span class="label">exemplo</span>
</section>

Essa estrutura pode ser representada como um objeto JavaScript:

{
    tag: "section",
    props: {
        id: "container"
    },
    children: [
        {
            tag: "span",
            props: {
                class: "label"
            },
            children: [
                "exemplo"
            ]
        }
    ]
}

Como o DOM possui uma estrutura hierárquica, é possível representá-lo por meio de objetos JavaScript. Os elementos nativos do navegador carregam consigo inúmeras propriedades e eventos — até mesmo um elemento vazio exige recrusos consideráveis.

A vantagem do Virtual DOM está na performance: quando ocorrem mudanças, o algoritmo de comparação (diff) identifica exatamente quais nós precisam ser atualizados, evitando re-renderizações desnecessárias da página inteira.

  1. A Função h no Vue

No Vue, a função h é um alias para createElement. Seu propósito é gerar nós virtuais (VNodes) que descrevem o que deve ser exibido na tela.

Ao configurar uma instância do Vue, frequentemente utilizamos a opção render:

const instancia = new Vue({
    render: function(criarElemento) {
        return criarElemento(MeuComponente)
    }
})
  1. Compilação de JSX

Ao escrever JSX em um arquivo como principal.jsx:

function montarEstrutura() {
    return (
        <div id="container">
            <p class="mensagem">Olá mundo</p>
        </div>
    )
}

O Babel transforma esse código em chamadas à função h:

function montarEstrutura() {
    return h("div", {
        id: "container"
    }, h("p", {
        class: "mensagem"
    }, "Olá mundo"))
}

A função h pode ser implementada da seguinte forma:

function h(etiqueta, atributos, ...descendentes) {
    return {
        tag: etiqueta,
        props: atributos || {},
        children: descendentes.flat()
    }
}

De acordo com a documentação oficial, createElement não retorna um elemento DOM real. O resultado é chamado de descrição de criação de nó (createNodeDescription), pois contém apenas as informações necessárias para que o Vue saiba qual estrutura renderizar. Esses objetos são denominados VNodes (nós virtuais).

  1. Parâmetros da Função createElement

A função createElement aceita três argumentos:

  • Primeiro argumento — nome da tag, objeto de opções de componente ou função (obrigatório);
  • Segundo argumento — objeto com atributos e propriedades do elemento (opcional);
  • Terceiro argumento — nós filhos, podendo ser uma string ou array de VNodes (opcional).

Exemplo compartaivo entre template e render function:

<!-- Usando template -->
<div id="app">
    {{titulo}}
    <span>{{descricao}}</span>
</div>

<!-- Usando render function -->
render: function(criarElemento) {
    return criarElemento("div", { id: "app" }, [
        this.titulo,
        criarElemento("span", this.descricao)
    ])
}

Observe que, quando o elemento pai possui texto diretamente, esse conteúdo deve vir como primeiro item do array no terceiro argumento.

  1. Renderização Condicional com Render Functions

<!-- Template equivalente -->
<ul v-if="lista.length">
    <li v-for="item in lista">{{ item.nome }}</li>
</ul>
<p v-else>Nenhum registro</p>

<!-- Render function -->
data: {
    lista: [
        { nome: "Ana" },
        { nome: "Bruno" },
        { nome: "Carlos" }
    ]
},
render: function(criarElemento) {
    if (this.lista.length) {
        return criarElemento("ul", this.lista.map(function(item) {
            return criarElemento("li", item.nome)
        }))
    } else {
        return criarElemento("p", "Nenhum registro")
    }
}

Tags: vue virtual-dom render-function h-function createElement

Publicado em 6-14 16:01 por Thomas