Guia 36 de 53
Views e Markup do Verniz
Componentes como funções, marcação parecida com HTML, interpolação segura e Views renderizadas no servidor sem linguagem de modelo.
Nesta página
Um componente Verniz é uma função Zolo que retorna View. Não há classe base, tabela de registro nem uma segunda linguagem de expressões.
Markup é Zolo¶
use std::html::{article, h2, p, View}
fn PostCard(titulo: str, resumo: str) -> View {
<article class="post">
<h2>{titulo}</h2>
<p>{resumo}</p>
</article>
}O parser baixa isso para a mesma representação da sintaxe builder:
article(class: "post") {
h2() { titulo }
p() { resumo }
}Use a forma mais clara. Componentes e elementos HTML seguem as mesmas regras de chamada, inclusive argumentos nomeados e valores padrão.
Texto, expressões e controle de fluxo¶
Dentro do markup, texto é literal. Chaves voltam para a linguagem Zolo completa:
fn Resultados(itens: [str], mostrar_vazio: bool) -> View {
<section>
{if itens.len() == 0 && mostrar_vazio {
<p>Nenhum resultado.</p>
}}
{for item in itens {
<p key={item}>{item}</p>
}}
</section>
}Use comentários HTML dentro do markup: <!-- nota -->. Comentários Zolo // e /* */ são aceitos entre atributos da tag.
Seguro por padrão¶
Texto interpolado e atributos são escapados. Um título com <script> vira texto, não markup executável. Use raw(valor) somente para HTML que já atravessou uma fronteira de confiança com segurança.
Documentos, fragmentos e rotas¶
Use document, head e body para páginas completas, ou fragment para irmãos sem wrapper. render(view) serializa uma View explicitamente.
Uma rota HTTP pode retornar View diretamente. O servidor renderiza e escolhe o content type HTML. Ele também serve o runtime do Verniz em /_zolo/client.js quando a página inclui client_script().
Elementos de texto raw¶
Os corpos de <style> e <script> são lidos como CSS e JavaScript, não como markup. Um <style> estático dentro do componente é escopado e içado por padrão; escreva <style global> para CSS do documento.
Próximo: Ilhas, Signals e Actions.
Elementos condicionais com v:if¶
Use v:if={condition} quando uma condição decide se um elemento inteiro existe. Uma condição falsa evita a chamada do componente e a avaliação de suas propriedades e filhos. No exemplo, expensive() só executa para elementos visíveis. A mesma regra vale para HTML e componentes coletados com std::ui.
use std::html::{div, span, render}
use std::ui::{collect}
var calls = 0
fn expensive() -> str { calls += 1; return "visible" }
let html = <div>
<span v:if={false}>{expensive()}</span>
<span v:if={true}>{expensive()}</span>
</div>
assert_eq(render(html), "<div><span>visible</span></div>")
assert_eq(calls, 1)
struct UiNode { text: str, children: [Any] }
fn Label(value: str) -> UiNode { UiNode.new(text: value, children: []) }
fn Panel(children: Any = nil) -> UiNode { UiNode.new(text: "panel", children: collect(children)) }
let panel = <Panel>
<Label v:if={false} value={expensive()}/>
<Label v:if={true} value={expensive()}/>
</Panel>
assert_eq(panel.children.len(), 1)
assert_eq(panel.children[0].text, "visible")
assert_eq(calls, 2)
print(render(html))
print(panel.children[0].text)
print(calls)A condição booleana executa uma vez. Um elemento ausente não acrescenta um filho. v:if exige uma expressão explícita e pode aparecer uma vez por elemento. Blocos {if ...} continuam úteis para vários elementos. Atualizações reativas usam o caminho de renderização condicional existente.
Este exemplo funciona na VM embarcada do playground e nos modos VM, native e LLVM da CLI. O wasm-aot independente ainda rejeita a coleta de componentes de std::ui usada aqui, pois ela depende do transporte de exceções (TryCallEnv). Capturar uma falha da validação booleana em runtime também exige transporte de exceções (TryCall), ainda indisponível nesse backend. v:if em si funciona no wasm-aot quando as dependências do componente são suportadas.
DOCS / OPINIÃO
Esta página deixou alguma pergunta?
Conte onde a explicação perdeu você. A documentação também faz parte da experiência da linguagem.