Estou usando Lit para renderizar uma lista aninhada. Se eu inserir os elementos da minha lista em um array com as sublistas inseridas como html
objetos de modelo Lit completos, tudo ficará bem. Posso renderizar a lista aninhada com o modelo html`<ul>${myArray}</ul>`
.
Entretanto, se eu, em vez disso, enviar sublistas como suas partes individuais ( <ul>
, <li>Sub-First
, ..., </ul>
), os elementos UL parecem ser renderizados fora de ordem como <ul></ul><li>Sub-First
.
Exemplo de trabalho completo (assumindo que você tenha uma cópia do código Lit conforme lit-all.min.js
baixado):
render-list.html
<!DOCTYPE html>
<html>
<head>
<script type="module" src="render-list.js"></script>
</head>
<body>
<render-list type="1"></render-list>
<render-list type="2"></render-list>
</body>
</html>
render-list.js
import {LitElement, html} from "./lit-all.min.js";
export class RenderList extends LitElement {
static properties = {
type: {type: Number}
};
constructor() {
super();
this.type = 0;
}
render() {
if (this.type == 1) {
let lst = [];
lst.push(html`<li>One`);
lst.push(html`<li>Two`);
let sublst = [];
sublst.push(html`<li>Sublist One`);
sublst.push(html`<li>Sublist Two`);
lst.push(html`<ul>${sublst}</ul>`);
lst.push(html`<li>Three`);
return html`
<h1>This list rendering works</h1>
<ul>${lst}</ul>
`;
}
else {
let lst = [];
lst.push(html`<li>One`);
lst.push(html`<li>Two`);
lst.push(html`<ul>`);
lst.push(html`<li>Sublist One`);
lst.push(html`<li>Sublist Two`);
lst.push(html`</ul>`);
lst.push(html`<li>Three`);
return html`
<h1>This list rendering doesn't work</h1>
<ul>${lst}</ul>
`;
}
}
}
customElements.define("render-list", RenderList);
Isso resulta no seguinte:
E olhando nas ferramentas do desenvolvedor aparece a segunda lista renderizada como:
<ul>
<li>One
<li>Two
<ul></ul>
<li>Sublist One
<li>Sublist Two
<li>Three
<ul>
Claramente não estou entendendo algo sobre a maneira como o Lit usa modelos aqui. Por que a segunda solução não funciona?
O motivo pelo qual sua segunda abordagem não funciona é porque o Lit processa cada modelo individualmente. Quando você envia apenas "ul" sem seu conteúdo e a tag de fechamento ao mesmo tempo, o Lit o trata imediatamente como um elemento completo (vazio) e o fecha. Ele não espera que você envie posteriormente elementos "li" e um "ul" para completá-lo. Em outras palavras, o Lit exige que cada modelo enviado forme um fragmento HTML válido. Ele não reúne modelos parciais separados em uma estrutura DOM completa. No seu primeiro caso (funcional), você envia corretamente um "ul"..."/ul" completo como um modelo:
Dessa forma, o Lit reconhece a hierarquia e a renderiza corretamente. No seu segundo caso (quebrado), você insere a tag de abertura separadamente:
Fazendo com que ele feche imediatamente após a tag de abertura em tempo de execução.
Você pode corrigir isso agrupando sua lista aninhada em um único modelo.
Ou melhor ainda, use uma abordagem orientada a dados, na qual você mapeia seus dados e gera elementos "li" e "ul" aninhados corretamente dentro da função de renderização.
O Lit renderiza instâncias de modelo no DOM, não texto bruto. O Lit não consegue "adivinhar" que você pretendia agrupá-las em um único
<ul>
bloco, em vez disso, injeta-as lado a lado no elemento pai. É por isso que elas estão sendo construídas como elementos irmãos em vez de aninhadas.Quando você conta:
Basicamente, você está dizendo para criá-lo
ul
como um componente independente, depoisli
como outro independente, e então</ul>
isso não funcionará porque as tags de fechamento não podem ser usadas como independentes.Em vez disso, crie estruturas completas dentro de um bloco HTML sempre que houver hierarquia.
Tente algo assim:
Isso ajudará o
<ul>
e o<li>
a serem construídos como um único componente.Aqui está o guia de Lit