- Aprender
- Computação e TI
- Programação
- Programação em JavaScript
- DOM em JavaScript
DOM em JavaScript: o Modelo de Objetos do Documento
BásicoAula 5 de 9 do curso Curso de Programação em JavaScript
O que você vai aprender
- Explique o que é o Modelo de Objetos do Documento, como o navegador o constrói a partir do HTML e como seus nós se relacionam, para você se localizar em qualquer página.
- Descrever o DOM como uma árvore de nósExplique o que é o DOM, como o navegador o constrói a partir do HTML, quais tipos de nós ele contém e como ele difere do código-fonte HTML.
- Navegar de um elemento para seu pai, seus filhos e seus irmãosPercorra a árvore a partir de qualquer elemento até seus parentes, escolha entre as propriedades que incluem nós de texto e as que retornam apenas elementos e encontre o ancestral correspondente mais próximo.
- Descrever o DOM como uma árvore de nós
- Encontre exatamente os elementos de que um script precisa usando seletores CSS, trate elementos ausentes e trabalhe com coleções de elementos correspondentes.
- Selecionar um único elementoEncontre um elemento com querySelector ou getElementById, pesquise dentro de uma parte da página e trate o caso em que não há correspondência.
- Selecionar vários elementos e trabalhar com os resultadosSelecione todos os elementos correspondentes, percorra os resultados, converta-os em um vetor quando necessário e saiba quando uma coleção se atualiza sozinha.
- Selecionar um único elemento
- Atualize o texto dos elementos e os atributos e propriedades que os controlam, escolha o método seguro quando o conteúdo vier de usuários ou dados e mantenha dados extras nos elementos.
- Alterar o texto e o HTML dentro de um elementoLeia e substitua o conteúdo de um elemento com textContent, innerText e innerHTML e proteja as páginas contra código injetado.
- Ler e definir atributos e propriedadesTrabalhe com atributos por meio de getAttribute e setAttribute e com as propriedades correspondentes dos elementos, e trate atributos booleanos e diferenças entre os dois.
- Armazenar dados nos elementos e ler campos de formulárioMantenha informações extras nos elementos com atributos de dados e leia e defina o valor atual dos campos de formulário.
- Alterar o texto e o HTML dentro de um elemento
- Alterne classes CSS, defina estilos em linha quando um valor for calculado, leia os estilos aplicados pelo navegador e mostre ou oculte partes de uma página.
- Adicionar, remover e alternar classes CSSAltere a aparência de um elemento alternando classes com classList e mantenha as regras visuais na folha de estilos.
- Definir estilos em linha e ler estilos computadosDefina estilos em linha pela propriedade style quando um valor for calculado em tempo de execução, remova-os depois e leia os estilos que o navegador realmente aplica.
- Mostrar e ocultar partes de uma páginaOculte e revele elementos com o atributo hidden ou uma classe, escolha entre as formas de tornar algo invisível com CSS e mantenha o estado claro para usuários de leitores de tela.
- Adicionar, remover e alternar classes CSS
- Construa novos elementos em JavaScript, coloque-os exatamente onde devem ficar e remova, substitua ou copie elementos para que a página mude sem ser recarregada.
- Criar novos elementos e inseri-losCrie elementos com createElement, preencha-os com texto e atributos e insira-os no fim, no início ou ao lado de outro elemento.
- Remover, substituir e copiar elementosRetire elementos da página, esvazie um contêiner, substitua um elemento por outro e faça cópias com cloneNode.
- Criar novos elementos e inseri-los
- Transforme vetores de dados em listas e tabelas na página, construa vários itens com eficiência e mantenha a página atualizada conforme os dados mudam.
- Construir itens de lista e linhas de tabela a partir de um vetorTransforme um vetor de objetos em itens de lista ou linhas de tabela com textContent, mostre resultados adequados para listas vazias e valores ausentes e vincule cada elemento aos seus dados.
- Construir vários itens com eficiência usando fragmentos e elementos templateInsira vários elementos novos em uma etapa com um DocumentFragment ou uma única chamada de append e reutilize marcação escrita em um elemento template HTML.
- Atualizar a página quando os dados mudaremMantenha os dados como única fonte de verdade, renderize novamente a partir deles após cada alteração e mostre visões filtradas, ordenadas e resumidas sem perder os dados originais.
- Construir itens de lista e linhas de tabela a partir de um vetor
Guia de estudo de DOM em JavaScript
1Ler a página como uma árvore
O navegador transforma HTML em objetos que JavaScript pode ler e alterar. Esses objetos formam uma árvore, portanto encontrar um elemento da página também exige compreender onde ele fica entre os outros nós. Comece relacionando tags conhecidas aos objetos no navegador. Depois, acompanhe as relações entre pais, filhos e irmãos, prestando atenção aos nós de texto criados a partir de espaços e quebras de linha. As DevTools permitem ver essa árvore enquanto seu código a altera.
1.1 HTML se transforma em uma árvore de objetos
O Modelo de Objetos do Documento, ou DOM, é a árvore dinâmica de objetos da página mantida pelo navegador. JavaScript lê e altera esses objetos para atualizar a página sem recarregá-la. O navegador fornece a API DOM; JavaScript é a linguagem usada para chamá-la.
Comece pelo documento
document é o ponto de entrada. document.documentElement refere-se a <html>, document.head a <head> e document.body a <body>. A aba do navegador é representada por window, cuja propriedade document se refere a esse documento.
Cada item da árvore é um nó. Elementos representam tags; nós de texto contêm caracteres; nós de comentário contêm comentários HTML; o nó de documento fica acima dos elementos da página. Seus valores de nodeType são, respectivamente, 1, 3, 8 e 9. Todo elemento é um nó, mas texto e comentários não são elementos.
Leia as relações familiares
<ul id="menu"><li>Home</li><li>About</li></ul>
A lista é pai de dois elementos de item irmãos. Cada item é seu filho. O primeiro item tem um nó de texto filho que contém “Home”. A lista é ancestral desse nó de texto, e o texto é descendente da lista. Essas relações descrevem o aninhamento, não posições na tela.
Espaços e quebras de linha entre tags geralmente se tornam nós de texto com espaços em branco. Uma lista indentada pode, portanto, ter dois elementos filhos, mas mais de dois nós filhos. children e firstElementChild retornam apenas elementos; childNodes e firstChild incluem texto e comentários.
Compare a árvore com o código-fonte
A análise sintática transforma a marcação na árvore e pode completá-la ou corrigi-la. Linhas escritas diretamente dentro de uma <table> recebem um pai <tbody>. Elementos <html>, <head> ou <body> ausentes também podem ser adicionados. Selecione elementos da árvore real, incluindo os adicionados pelo analisador.
Alterações feitas por scripts afetam o DOM atual do navegador, não o arquivo HTML no servidor. “Ver código-fonte da página” mostra o HTML original, enquanto o painel Elementos das DevTools mostra a árvore atual. Recarregar constrói um novo DOM; uma edição, por si só, não salva os dados que a originaram.
Inspecione um objeto
Clique com o botão direito em um elemento e escolha “Inspecionar”. Digite $0 no Console para se referir ao elemento selecionado. console.log($0) o apresenta como marcação; console.dir($0) mostra suas propriedades. Expanda uma lista indentada para ver os nós de espaços em branco junto aos elementos de item.
Principais conclusões
- O DOM é uma árvore fornecida pelo navegador que JavaScript pode ler e alterar.
- Elementos, texto, comentários e o documento são tipos diferentes de nós.
- Espaços em branco e elementos adicionados pelo analisador podem fazer o DOM diferir do HTML escrito.
- Inspecione a árvore atual nas DevTools; uma edição no DOM não reescreve o HTML do servidor.
1.2 Acompanhar pais, filhos e irmãos
As propriedades da árvore permitem que um script alcance conteúdo próximo a partir de um elemento que já possui. Escolha se esse caminho deve incluir texto e comentários ou apenas elementos.
Escolha nós ou elementos
As propriedades para nós incluem parentNode, childNodes, firstChild, lastChild, previousSibling e nextSibling. Suas correspondentes para elementos são parentElement, children, firstElementChild, lastElementChild, previousElementSibling e nextElementSibling. children é uma HTMLCollection; childNodes é uma NodeList.
<ul id="tasks">
<li>Buy milk</li>
<li>Call Sam</li>
</ul>
Aqui, tasks.childNodes.length é 5: dois elementos e três trechos de espaços em branco. tasks.children.length é 2. tasks.firstChild é texto com espaços em branco, enquanto tasks.firstElementChild.textContent é “Buy milk”. Os índices começam em 0, portanto tasks.children[1] é o segundo item.
Siga um caminho curto
const tasks = document.querySelector("#tasks");
const first = tasks.firstElementChild;
const second = first.nextElementSibling;
console.log(second.textContent);
console.log(second.parentElement === tasks);
O resultado é “Call Sam”, seguido de true. tasks.lastElementChild alcança o mesmo item diretamente, assim como tasks.children[tasks.children.length - 1].
Trate um parente ausente
O nextElementSibling do último item é null. Um elemento sem elementos filhos tem firstElementChild === null e uma coleção children vazia. O parentNode do elemento HTML raiz é o documento, mas seu parentElement é null.
Ler uma propriedade de null lança um erro de tipo. Verifique antes ou use second.nextElementSibling?.textContent, que fornece undefined quando não existe um próximo elemento.
Encontre um item que contém o elemento
closest(selector) verifica o elemento atual e depois seus ancestrais, retornando a correspondência mais próxima ou null. Um botão dentro de <li class="task" data-id="7"> pode usar button.closest(".task"); o dataset.id do item encontrado é “7”. Já matches(selector) testa apenas o elemento atual e retorna um booleano.
Caminhos longos como el.parentElement.parentElement.nextElementSibling dependem do aninhamento exato. Um elemento envoltório adicionado muda seu significado. Use seletores para regiões nomeadas, navegação curta para relações estáveis e closest() para encontrar um item que contém o elemento.
Principais conclusões
- Use a navegação apenas por elementos quando espaços em branco e comentários devem ser ignorados.
- Coleções começam no índice 0; seu tamanho é uma contagem, não o último índice.
- Um parente ausente é null; verifique antes de ler suas propriedades.
- closest() verifica o próprio elemento e depois seus ancestrais.
- matches() testa o elemento atual sem percorrer a árvore.
2Encontrar elementos da página
Uma alteração no DOM começa com uma referência ao elemento certo. Seletores CSS permitem pesquisar a página inteira ou apenas um contêiner, enquanto métodos de coleção permitem trabalhar com vários resultados. O valor de retorno é importante: uma pesquisa pode fornecer um elemento ou null, outra sempre fornece uma coleção. Você também precisa saber quando o script é executado e se uma coleção salva muda conforme a página muda, pois ambos afetam o que seu código encontra.
2.1 Encontrar um elemento e verificar o resultado
Um seletor transforma a descrição de um elemento em uma referência a um objeto. Comece com a menor pesquisa que identifique o elemento necessário e verifique se ele foi encontrado antes de alterá-lo.
Pesquise com um seletor CSS ou um id
document.querySelector(selector) retorna o primeiro elemento correspondente na ordem do documento. Ele aceita seletores CSS conhecidos: "h1", ".price", "#cart", "nav a" ou 'input[type="email"]'. Se não houver correspondência, retorna null.
document.getElementById("cart") procura um id diretamente. Seu argumento é o id puro. getElementById("#cart") procura um id que realmente inclua o caractere cerquilha, enquanto querySelector("cart") procura uma tag <cart>. Use querySelector("#cart") para o seletor de id.
Ids devem ser únicos. Se uma marcação copiada der o mesmo id a dois elementos, essas pesquisas retornarão o primeiro na ordem do documento. Corrija a marcação duplicada em vez de esperar que uma pesquisa por id alcance a segunda cópia.
Pesquise dentro de um contêiner
Suponha que vários cartões tenham um elemento com a classe name. Selecione primeiro o cartão de perfil e depois pesquise seus descendentes:
const card = document.querySelector("#profile");
if (card) {
const name = card.querySelector(".name");
if (name) name.textContent = "Maya";
}
A pesquisa interna fica limitada ao cartão de perfil, portanto um .name anterior em outro lugar não interfere. O próprio contêiner não é candidato em sua pesquisa com querySelector(). Elementos comuns oferecem esse método, mas getElementById() pertence a document.
Distinga ausência de correspondência de seletor inválido
Uma pesquisa válida sem correspondência fornece null. Tentar definir null.textContent lança um erro de tipo, portanto verifique conteúdo opcional:
const banner = document.querySelector(".banner");
if (banner) banner.textContent = "Sale ends Friday";
Um seletor CSS inválido lança um erro de sintaxe antes que possa haver um resultado. Para <p id="1st">, querySelector("#1st") é inválido porque o algarismo precisa de escape nesse seletor CSS de id. getElementById("1st") usa um id literal e funciona diretamente.
Execute depois que a marcação necessária existir
Um script externo clássico em <head> é executado antes de o navegador analisar o corpo. Uma pesquisa por um parágrafo posterior retorna, portanto, null, mesmo quando o HTML o contém. Use <script src="app.js" defer></script> para executar depois da análise, use um script de módulo ou coloque o script logo antes de </body>. Scripts de módulo têm execução adiada por padrão. O atributo defer não tem efeito em um script clássico incorporado ao HTML.
Em uma página HTML que começa com <!DOCTYPE html>, seletores de id e classe diferenciam maiúsculas de minúsculas: .Price não encontra class="price". Seletores de tags HTML não fazem essa distinção, portanto "LI" e "li" correspondem a itens de lista. Quando uma pesquisa falhar, verifique a escrita, a sintaxe do seletor, o contêiner de pesquisa e o momento de execução do script.
Principais conclusões
- querySelector() retorna a primeira correspondência ou null.
- getElementById() recebe um id puro; querySelector() recebe a sintaxe de um seletor CSS.
- Pesquise os descendentes de um contêiner quando uma classe aparecer em várias regiões da página.
- Uma correspondência ausente retorna null; uma sintaxe de seletor inválida lança um erro.
- Execute o código DOM depois que sua marcação tiver sido analisada.
- Mantenha ids únicos e respeite maiúsculas e minúsculas em seletores de id e classe.
2.2 Trabalhar com coleções de elementos correspondentes
Use querySelectorAll() quando a mesma operação deve ser aplicada a vários elementos. Seu resultado é uma coleção, portanto você precisa decidir como percorrê-la e se precisa de um retrato estático ou de uma visão dinâmica.
Leia e percorra uma NodeList
document.querySelectorAll(".note") retorna uma NodeList de elementos correspondentes na ordem do documento. Sem correspondências, o resultado é uma NodeList vazia de tamanho 0. A coleção em si ainda é avaliada como verdadeira; if (notes) não informa se ela contém elementos. Verifique notes.length.
Uma NodeList oferece índices, length, forEach() e for...of, mas não é um vetor e não tem map(), filter() nem reduce(). Converta-a quando precisar desses métodos:
const weights = Array.from(document.querySelectorAll(".weight"))
.map(el => Number(el.textContent));
const total = weights.reduce((sum, weight) => sum + weight, 0);
Para elementos que contêm “4.5”, “12” e “3.25”, o vetor é [4.5, 12, 3.25] e o total é 19,75 kg. A conversão para números é importante porque os valores de texto são cadeias de caracteres.
Uma coleção não é um elemento combinado. Definir notes.textContent não altera nenhuma nota, e notes.classList.add("saved") lança um erro porque a NodeList não tem classList. Aplique a alteração a cada elemento:
const notes = document.querySelectorAll(".note");
notes.forEach(note => note.classList.add("saved"));
Compare resultados estáticos e dinâmicos
A NodeList de querySelectorAll() é estática: seus membros são fixados quando a pesquisa é executada. Os elementos aos quais ela se refere continuam sendo os objetos reais, portanto seu texto ou suas classes podem mudar.
getElementsByClassName("note") e getElementsByTagName("li") retornam uma HTMLCollection dinâmica. children também é dinâmica. Essas coleções atualizam seus membros quando o DOM muda. Elas oferecem índices e for...of, mas não forEach().
Em uma lista com três elementos .item, salve tanto list.getElementsByClassName("item") quanto list.querySelectorAll(".item"). Acrescente um quarto elemento correspondente. A coleção dinâmica passa a ter tamanho 4; o retrato estático continua com tamanho 3.
Evite a armadilha de uma coleção dinâmica que diminui durante o laço
Suponha que quatro elementos pertençam a uma coleção dinâmica chamada live:
for (let i = 0; i < live.length; i++) {
live[i].classList.remove("item");
}
Remover a primeira classe retira esse elemento da coleção. O próximo elemento é deslocado para o índice 0, mas o laço avança para o índice 1 e o ignora. Apenas dois dos quatro perdem a classe. Percorra Array.from(live) ou um retrato estático de querySelectorAll() ao alterar os membros da coleção.
Verifique os espaços nos seletores
.task.done significa um elemento com ambas as classes. .task .done significa um descendente .done dentro de um .task. Para <li class="task done">, conte os itens concluídos com document.querySelectorAll(".task.done").length. Uma vírgula combina seletores: "h2, h3" retorna correspondências na ordem do documento, não todos os títulos de um tipo seguidos pelos do outro.
Principais conclusões
- Percorra os membros da coleção para alterar seu conteúdo ou suas classes.
- querySelectorAll() retorna uma NodeList estática; um resultado vazio tem tamanho 0.
- Converta coleções com Array.from() ou espalhamento antes de usar métodos exclusivos de vetores.
- Coleções dinâmicas mudam seus membros conforme os elementos correspondentes mudam.
- Faça um retrato estático antes de um laço que remova membros de uma coleção dinâmica.
- Um espaço em um seletor muda a relação que está sendo pesquisada.
3Atualizar conteúdo e dados de elementos
Um elemento contém vários tipos de informação: texto visível, estrutura HTML, atributos e propriedades JavaScript. Escolher a informação certa permite atualizar um rótulo, alterar um link, ler um campo ou vincular um item exibido aos seus dados. O mesmo texto pode ser tratado como caracteres comuns ou analisado como HTML, com resultados muito diferentes. Acompanhe essas diferenças para que as atualizações mostrem o conteúdo desejado e o texto externo seja tratado com segurança.
3.1 Escolher texto ou HTML para atualizar conteúdo
Texto e HTML são entradas diferentes. Texto simples deve aparecer como caracteres; HTML descreve elementos que o navegador deve construir. Escolher entre eles afeta tanto a estrutura da página quanto a possibilidade de texto externo executar código indesejado.
Leia e substitua texto
Para <p id="msg">Total: <strong>3</strong> items</p>, msg.textContent é “Total: 3 items”. Ele une o texto dos descendentes do elemento sem incluir suas tags e inclui texto ocultado por CSS.
Definir textContent substitui todos os filhos por um nó de texto. Após msg.textContent = "Cart is empty", o filho <strong> deixa de existir dentro do parágrafo. Definir msg.textContent = "<b>Hi</b>" exibe os caracteres literais “Hi”; não cria um elemento em negrito.
Valores de texto são cadeias de caracteres. Se um contador contém “4”, count.textContent + 1 produz “41”. Converta antes de somar:
count.textContent = Number(count.textContent) + 1;
A soma fornece o número 5, e a atribuição exibe sua forma textual, “5”.
Leia o texto que segue o layout
Em um elemento renderizado, innerText acompanha o texto e o layout exibidos. Ele omite descendentes ocultos com display: none e inclui quebras de linha que seguem o layout. Lê-lo pode exigir um cálculo de layout. Use textContent para o trabalho comum com texto; escolha innerText quando precisar do texto renderizado. Se o próprio elemento estiver desconectado ou não for renderizado, innerText recorre ao seu conteúdo de texto.
Analise HTML intencionalmente
innerHTML lê a marcação dentro de um elemento. Defini-lo analisa a cadeia de caracteres e substitui os filhos:
msg.innerHTML = "Total: <strong>5</strong> items";
Isso cria um novo elemento <strong>. É adequado para marcação que você escreveu e controla. Para texto de um usuário ou de dados externos, use textContent e construa a estrutura com createElement().
Inserir HTML não confiável pode permitir injeção de scripts entre sites (XSS): código controlado por um invasor é executado no navegador do visitante. Uma imagem injetada pode conter um atributo onerror que executa código quando a imagem não carrega. Tags de script inseridas por innerHTML não são executadas, mas isso não torna seguro outro HTML injetado. Bloquear apenas tags de script deixa esse caminho de ataque aberto.
Preserve os filhos existentes ao adicionar conteúdo
list.innerHTML += "<li>New</li>" lê a marcação existente, concatena uma cadeia de caracteres e depois analisa e substitui todo o conjunto de filhos. Ele não preserva a identidade dos objetos. Uma variável que contém um filho antigo continua contendo esse objeto desconectado, e valores digitados em campos substituídos podem ser perdidos. Use append() com novos nós, ou insertAdjacentHTML("beforeend", markup) para marcação confiável, para adicionar conteúdo sem recriar os filhos existentes.
outerHTML inclui a própria tag do elemento e também seu conteúdo. Defini-lo substitui o próprio elemento. Uma referência salva continua apontando para o elemento antigo e desconectado após a substituição; ela não passa automaticamente a apontar para o novo.
Principais conclusões
- textContent trata texto simples e substitui os filhos do elemento quando recebe um valor.
- Converta texto em número antes de fazer operações aritméticas.
- innerText segue o layout renderizado; innerHTML analisa a marcação.
- Mantenha texto não confiável fora de atribuições que analisam HTML.
- innerHTML += recria os filhos existentes; append() os preserva.
- Uma atribuição a outerHTML substitui o elemento e deixa as referências antigas desconectadas.
3.2 Distinguir atributos de propriedades de objetos
Um atributo é um nome e um valor no HTML. Uma propriedade pertence ao objeto JavaScript que representa um elemento. Muitos atributos padrão têm propriedades correspondentes, mas essas propriedades podem processar valores ou informar outro tipo de estado.
Trabalhe com um atributo pelo nome
Para <img src="logo.png" alt="Company logo">, o navegador inicializa propriedades como img.src e img.alt. Você também pode usar métodos que recebem o nome do atributo como uma cadeia de caracteres:
getAttribute(name)retorna uma cadeia de caracteres, ounullse o atributo estiver ausente.setAttribute(name, value)adiciona ou altera um atributo e armazena seu valor como texto.hasAttribute(name)informa se o atributo está presente.removeAttribute(name)o remove.
Por exemplo, link.setAttribute("href", "https://example.com/help") altera o destino de um link. Se não houver um atributo target, link.getAttribute("target") retorna null, não uma cadeia de caracteres vazia.
Leia o valor de que você realmente precisa
Em uma página no endereço https://example.com/shop/, o link <a href="/about"> tem o valor de atributo “/about”. Sua propriedade href é a URL resolvida, “https://example.com/about”. Leia o atributo quando precisar do valor exatamente como foi escrito e a propriedade quando precisar da URL resolvida.
Propriedades podem ter tipos diferentes de cadeia de caracteres. button.disabled é um booleano; input.maxLength é um número. Métodos de atributo ainda retornam cadeias de caracteres ou null. Nomes de propriedades também são nomes JavaScript que diferenciam maiúsculas de minúsculas: el.id funciona, enquanto el.ID é uma propriedade diferente e normalmente é undefined.
A maioria dos nomes é conhecida, mas há exceções. O atributo HTML class é disponibilizado por className e classList. O atributo for de um rótulo corresponde à propriedade htmlFor:
label.htmlFor = "email";
Isso associa o rótulo ao elemento cujo id é “email”.
Trate atributos booleanos pela presença
Atributos booleanos incluem disabled, checked, required e readonly. Sua presença torna o atributo verdadeiro, mesmo que seu texto seja “false”. Este código desabilita um botão:
button.setAttribute("disabled", "false");
Para habilitá-lo, defina button.disabled = false ou chame button.removeAttribute("disabled"). button.toggleAttribute("disabled", isBusy) adiciona o atributo quando isBusy é verdadeiro e o remove quando é falso.
Descreva controles de forma acessível
Atributos ARIA fornecem informações à tecnologia assistiva. Métodos de atributo são úteis para defini-los, como em button.setAttribute("aria-label", "Close dialog"), para dar nome a um botão que contém apenas um ícone. Seus valores são cadeias de caracteres; por exemplo, um valor de estado expandido é “true” ou “false”.
Use propriedades para operações comuns, como img.src = "photo.jpg" ou input.disabled = true. Use métodos de atributo quando o nome estiver em uma variável, quando o valor exato escrito for importante ou quando o atributo não tiver uma propriedade correspondente que você esteja usando.
Acompanhe uma alteração de propriedade até o HTML
const field = document.createElement("input");
field.disabled = true;
console.log(field.hasAttribute("disabled"));
console.log(typeof field.disabled);
console.log(typeof field.getAttribute("disabled"));
field.removeAttribute("disabled");
console.log(field.disabled);
Os resultados são true, “boolean”, “string” e false. Definir a propriedade adiciona o atributo booleano. Ler esse atributo ainda retorna texto, embora a propriedade seja um booleano. Removê-lo faz a propriedade voltar a ser falsa. O método e a propriedade mostram a mesma presença por meio de tipos de valor diferentes.
Principais conclusões
- Atributos armazenam valores HTML; propriedades podem fornecer valores com tipos definidos ou processados.
- getAttribute() retorna uma cadeia de caracteres ou null quando o atributo está ausente.
- Atributos booleanos são verdadeiros por sua presença, inclusive disabled="false".
- Use nomes de propriedades como className e htmlFor quando os nomes no HTML forem diferentes.
- Valores ARIA são cadeias de caracteres que descrevem o elemento para a tecnologia assistiva.
3.3 Vincular elementos a dados e ler campos
Um elemento pode carregar um id dos dados que exibe sem mostrar esse id na tela. Controles de formulário também contêm valores, mas seu conteúdo atual é lido por meio de propriedades. Ambos os tipos de valor frequentemente precisam ser convertidos antes de comparações ou operações aritméticas.
Armazene dados personalizados com atributos de dados
Nomes HTML que começam com data- armazenam informações para scripts:
<li data-task-id="17" data-priority="high">Prepare slides</li>
O objeto dataset disponibiliza esses atributos. Remova o prefixo data- e transforme cada hífen seguido de uma letra minúscula nessa letra maiúscula: data-task-id vira dataset.taskId. data-priority vira dataset.priority.
li.dataset.dueDate = "2026-11-05";
delete li.dataset.priority;
A atribuição cria data-due-date="2026-11-05". O delete remove data-priority. Atributos de dados também podem ser selecionados com seletores CSS de atributo, como '[data-priority="high"]'.
Um atributo inventado como taskid="17" é HTML inválido e não cria uma propriedade li.taskid. getAttribute("taskid") ainda pode lê-lo, mas data-task-id é a forma adequada para dados personalizados.
Converta valores de cadeia de caracteres intencionalmente
li.dataset.taskId é “17”, uma cadeia de caracteres. li.dataset.taskId === 17 é falso porque os tipos são diferentes. Quando os ids nos dados forem números, use Number(li.dataset.taskId) === 17. Um atributo de dados ausente fornece undefined. Atribuir li.dataset.count = 3 armazena o texto “3”.
Isso cria uma ligação útil entre um item exibido e seu objeto:
const id = Number(li.dataset.taskId);
const task = tasks.find(task => task.id === id);
A comparação agora usa dois números. Se nenhum objeto tiver esse id, find() retorna undefined; verifique antes de ler suas propriedades.
Leia o valor atual de um campo
Um <input> não contém o valor digitado como conteúdo de texto. Leia input.value, que é uma cadeia de caracteres, ou atribua-lhe um valor para alterar o campo. input.value = "" limpa o campo.
Para <input id="qty" value="1">, depois que o usuário digita 3, qty.value é “3”, mas qty.getAttribute("value") continua sendo “1”. O atributo fornece o valor inicial; a propriedade fornece o atual. Uma caixa de seleção funciona de modo semelhante: sua propriedade checked informa seu estado booleano atual, enquanto o atributo descreve o estado inicial de seleção.
Use o valor certo para cada controle
Até mesmo <input type="number"> tem um value que é uma cadeia de caracteres. Se a quantidade for “3” e cada item pesar 0,25 kg, Number(qty.value) * 0.25 fornecerá 0,75 kg. Mas qty.value + 1 fornece “31” porque + concatena uma cadeia de caracteres e um número. Um <select> retorna o valor da opção selecionada por meio de select.value. Para uma caixa de seleção, leia checkbox.checked, não checkbox.value, quando precisar saber se ela está selecionada.
Principais conclusões
- dataset mapeia data-task-id para taskId e armazena valores como cadeias de caracteres.
- Use delete em uma propriedade de dataset para remover seu atributo de dados.
- Converta ids de dados antes da comparação estrita com ids numéricos.
- Leia o conteúdo atual de input e select por meio de value.
- Leia o estado atual de seleção de uma caixa de seleção por meio de checked.
- Os atributos iniciais value e checked podem diferir das propriedades atuais dos controles.
4Controlar aparência e visibilidade
JavaScript pode alterar a aparência de uma página alternando classes, definindo um valor calculado em linha ou ocultando uma seção. Essas escolhas funcionam com o CSS que já está na página. Aprenda qual estado deve ficar em uma classe, quais valores precisam de unidades e como ler o estilo aplicado pelo navegador. Mostrar e ocultar também afeta o layout e a tecnologia assistiva, portanto mantenha os painéis visíveis e seus atributos de acessibilidade sincronizados.
4.1 Alternar classes sem perder o estilo básico
Mantenha regras visuais fixas no CSS e deixe que JavaScript altere as classes que selecionam essas regras. Uma classe pode expressar um estado como “concluído”, “ativo” ou “erro” sem repetir no código as cores e decorações correspondentes.
Adicione e remova nomes individuais de classe
Suponha que a folha de estilos contenha:
.done { text-decoration: line-through; color: #888; }
item.classList.add("done") aplica a aparência de concluído. item.classList.remove("done") remove esse estado, mantendo as outras classes intactas. Ambos os métodos aceitam vários nomes; adicionar uma classe existente ou remover uma ausente não causa problemas.
contains("done") retorna um booleano. replace("wide", "narrow") troca uma classe presente por outra. toggle("active") adiciona uma classe ausente ou remove uma presente, retornando se a classe existe depois da chamada.
Acompanhe uma alteração de classe
Comece com <div class="card">:
card.classList.add("active", "wide");
const active = card.classList.toggle("active");
const replaced = card.classList.replace("wide", "narrow");
Após a primeira linha, as classes são “card active wide”. A alternância remove “active”, portanto active é false e as classes passam a ser “card wide”. Substituir “wide” deixa “card narrow” e retorna true. Uma chamada posterior a card.classList.contains("active") resulta em false.
Defina uma classe a partir de uma condição
Quando os dados fornecem o estado desejado, passe um segundo argumento:
row.classList.toggle("overdue", daysLeft < 0);
Um daysLeft negativo garante a presença da classe; caso contrário, ela fica ausente. Repetir a chamada preserva esse estado. Uma chamada simples a toggle("overdue") inverteria o estado a cada execução.
Preserve o restante do atributo de classe
className é a cadeia completa de classes. card.className = "active" substitui todas as classes existentes, incluindo “card”. Use essa atribuição quando quiser substituir o conjunto inteiro; use classList para alterar estados individuais.
Passe nomes de classes puros, sem a pontuação de seletores CSS. classList.add(".active") adiciona um nome que contém um ponto literal; essa não é a classe à qual .active corresponde. Um único argumento não pode conter espaços: classList.add("big red") lança um InvalidCharacterError. Escreva classList.add("big", "red") para duas classes.
Verifique o CSS quando a aparência não mudar
Se uma classe não tiver efeito visível, inspecione seu nome e sua regra nas DevTools. Procure uma regra ausente ou escrita incorretamente e declarações sobrepostas, riscadas no painel Estilos.
Principais conclusões
- classList altera nomes individuais de classe e preserva as demais classes.
- toggle(name) retorna se a classe está presente depois da chamada.
- toggle(name, condition) define uma classe a partir dos dados sem inverter seu estado a cada execução.
- Uma atribuição a className substitui toda a cadeia de classes.
- Passe nomes puros separados, sem pontos de seletor ou espaços dentro de um nome.
4.2 Definir estilos calculados e ler estilos aplicados
Use classes para designs fixos e estilos em linha para valores calculados. O objeto style lê e escreve declarações em linha, não todas as regras que afetam um elemento.
Escreva valores CSS por meio de style
Nomes CSS com hífens se tornam propriedades JavaScript em notação camelCase. background-color vira backgroundColor, font-size vira fontSize e z-index vira zIndex:
box.style.backgroundColor = "gold";
box.style.width = "250px";
Valores de estilo são cadeias de caracteres. Inclua uma unidade quando a propriedade exigir. Em uma página no modo padrão, a atribuição box.style.width = 250 é ignorada porque uma largura diferente de zero precisa de uma unidade CSS. A cadeia “0” é válida para uma largura zero.
style.setProperty() recebe a grafia CSS:
box.style.setProperty("background-color", "gold");
document.documentElement.style.setProperty("--accent", "#0a7d5a");
A propriedade personalizada na raiz fornece o valor às regras que fazem referência a var(--accent).
Transforme um cálculo em um valor CSS
Uma barra de progresso mostra 3 tarefas concluídas de um total de 8:
const percent = (3 / 8) * 100;
bar.style.width = `${percent}%`;
A proporção 0,375 se torna 37,5 por cento. O literal de modelo fornece “37.5%”, incluindo a unidade necessária.
Remova uma sobrescrita temporária
Defina box.style.backgroundColor = "" ou chame box.style.removeProperty("background-color") para remover essa declaração em linha. O navegador aplica então as regras restantes da folha de estilos. Use o nome CSS com hífens em removeProperty().
Tenha cuidado com style.cssText. Atribuir box.style.cssText = "color: red" substitui todo o estilo em linha, portanto uma largura em linha existente é perdida. Alterar uma propriedade de estilo mantém intactas as outras declarações em linha.
Leia o que o navegador aplica
Se uma folha de estilos deixar um parágrafo vermelho, mas ele não tiver cor em linha, p.style.color será uma cadeia de caracteres vazia. Use getComputedStyle(p).color para obter o valor aplicado, geralmente “rgb(255, 0, 0)”. Valores computados são somente de leitura; altere a classe ou a declaração em linha para mudar a aparência.
Declarações em linha têm prioridade sobre regras comuns da folha de estilos, mas declarações !important aplicáveis podem prevalecer. Se uma alteração de classe parecer não surtir efeito, verifique se há uma sobrescrita em linha remanescente.
Principais conclusões
- style lê e escreve declarações em linha; a notação camelCase corresponde a nomes CSS com hífens.
- Forneça unidades nas cadeias de valores CSS quando necessário.
- setProperty() e removeProperty() recebem nomes CSS com hífens.
- Remova uma declaração em linha para permitir que as regras da folha de estilos voltem a ser aplicadas.
- getComputedStyle() informa os valores aplicados, incluindo estilos de regras CSS.
4.3 Ocultar conteúdo e manter seu estado claro
Ocultar um painel o mantém no DOM, pronto para voltar com seu conteúdo e os valores existentes nos campos. Removê-lo o retira da árvore. Escolha a ocultação para um painel que voltará e a remoção para um item cujos dados não existem mais.
Use a propriedade hidden
panel.hidden = true adiciona o estado comum de ocultação. O estilo padrão do navegador oculta o painel sem que ele ocupe espaço no layout. panel.hidden = false remove esse estado e o revela novamente.
Uma folha de estilos pode sobrepor esse padrão. Por exemplo, .panel { display: flex; } pode tornar visível um painel oculto. Quando o estado oculto deve sempre prevalecer, inclua:
[hidden] { display: none !important; }
Outra opção é controlar a visibilidade com uma classe CSS. Com .is-hidden { display: none; }, menu.classList.toggle("is-hidden", !isOpen) adiciona a classe de ocultação quando o menu está fechado. Verifique a folha de estilos se a classe estiver presente, mas outra declaração de display prevalecer.
Compare três formas de ocultar
display: none remove o espaço do elemento no layout e o oculta dos leitores de tela. visibility: hidden torna-o invisível enquanto mantém seu espaço e também o oculta dos leitores de tela. opacity: 0 torna-o transparente, mas mantém seu espaço; ele ainda pode ser clicado e continua disponível para leitores de tela. Portanto, a transparência por si só é uma forma inadequada de fechar um painel que não deve mais estar disponível.
Esses efeitos dizem respeito à visibilidade e ao layout, não à exclusão. Um campo oculto ainda pode manter o valor digitado nele porque o mesmo objeto permanece na árvore.
Mantenha a descrição do controle sincronizada
Um botão associado a um painel expansível deve informar se ele está expandido. Defina aria-expanded como a cadeia de caracteres “true” quando estiver aberto e “false” quando estiver fechado. Baseie esse valor e a visibilidade do painel no mesmo estado.
Para um painel de resposta que começa como <div id="answer-1" hidden>, com referências chamadas answer e button, execute:
const willOpen = answer.hidden;
answer.hidden = !willOpen;
button.setAttribute("aria-expanded", String(willOpen));
Inicialmente, answer.hidden é true, portanto willOpen é verdadeiro. A atribuição define hidden como falso e mostra o painel. O atributo do botão passa a ser “true”. Executar as mesmas instruções novamente começa com hidden falso, oculta o painel e escreve “false” no atributo.
Identifique uma inconsistência
Se o botão anunciar “expandido” enquanto o painel estiver oculto, os dois valores não foram atualizados juntos. Se hidden for verdadeiro, mas o painel ainda estiver visível, inspecione seu display computado e a regra CSS responsável. O primeiro problema é um estado inconsistente da aplicação; o segundo é um estilo que se sobrepõe ao estado oculto. Ler tanto as propriedades DOM quanto o CSS aplicado permite distingui-los.
Principais conclusões
- hidden mantém o conteúdo no DOM enquanto o oculta com o estilo padrão.
- Uma regra display explícita pode sobrepor hidden; inspecione ou garanta a aplicação da regra desejada.
- display: none remove o espaço; visibility: hidden preserva o espaço.
- opacity: 0 preserva a interação e a disponibilidade para leitores de tela.
- Atualize aria-expanded a partir do mesmo estado de abertura do painel.
5Construir e alterar a estrutura da página
A estrutura da página pode mudar enquanto ela está aberta. Construa um elemento na memória, preencha-o e insira-o no ponto certo da árvore. Os mesmos métodos de inserção podem mover um nó existente, portanto adicionar uma referência duas vezes não cria duas cópias. Remover, substituir e clonar fazem alterações diferentes na árvore e nas referências mantidas pelo script. Acompanhar essas referências ajuda a explicar por que uma variável antiga às vezes aponta para conteúdo desconectado.
5.1 Criar um nó, preenchê-lo e depois inseri-lo
Um novo elemento não aparece apenas porque você o criou. Primeiro crie o objeto, depois forneça conteúdo e atributos e, por fim, insira-o no documento. Antes da inserção, você pode montar uma estrutura aninhada inteira na memória.
Construa um item completo
const li = document.createElement("li");
li.textContent = "Water the plants";
li.className = "task";
li.dataset.id = "4";
document.querySelector("#tasks").append(li);
createElement("li") cria um elemento vazio. As linhas seguintes o preenchem; a última o insere como o último filho da lista de tarefas existente. O resultado é <li class="task" data-id="4">Water the plants</li>. A chamada precisa de um nome de tag, não de marcação: createElement("<li>") lança um InvalidCharacterError. Defina classes e atributos após a criação.
Para conteúdo aninhado, crie separadamente um span para o título e um botão, defina seus textos e chame li.append(title, button). Depois, insira o item montado na lista. document.createTextNode("…") cria texto diretamente; passar uma cadeia de caracteres para append() também insere um nó de texto.
Escolha uma posição de inserção
parent.append(...)adiciona depois dos filhos existentes.parent.prepend(...)adiciona antes dos filhos existentes.element.before(...)adiciona irmãos anteriores.element.after(...)adiciona irmãos posteriores.
Cada método aceita vários nós e cadeias de caracteres. As cadeias são tratadas como texto, portanto list.append("<li>New</li>") não constrói um item. Os sinais de menor e maior aparecem como caracteres dentro da lista.
Métodos mais antigos ainda aparecem no código. appendChild(node) aceita um nó e o retorna; não aceita uma cadeia de caracteres. append() retorna undefined. parent.insertBefore(newNode, referenceNode) insere um nó antes de um filho existente; usar null como referência adiciona ao fim.
Compreenda a diferença entre mover e copiar
Um nó pode ocupar apenas um lugar na árvore. Inserir um nó existente o move. Para uma lista na ordem a, b, c, list.prepend(list.lastElementChild) move c para o início, produzindo c, a, b. Ele não deixa um segundo c no fim.
Isso também explica um erro comum em laços: criar um <li> fora de um laço e acrescentá-lo repetidamente deixa apenas um item. Cada passagem altera e move o mesmo objeto. Crie um novo elemento dentro de cada passagem quando a página precisar de vários itens ou faça clones separados.
Insira marcação confiável ao lado do conteúdo existente
insertAdjacentHTML(position, markup) analisa HTML sem substituir os filhos existentes. Seus quatro nomes de posição são "beforebegin" e "afterend" para irmãos fora do elemento, e "afterbegin" e "beforeend" para filhos dentro dele. list.insertAdjacentHTML("beforeend", "<li>New</li>") acrescenta um item analisado. Use isso apenas para marcação confiável; texto externo deve ser inserido em textContent. insertAdjacentElement() e insertAdjacentText() usam os mesmos nomes de posição para um elemento ou texto simples.
Principais conclusões
- Criar, preencher e inserir são etapas separadas.
- append/prepend adicionam filhos; before/after adicionam irmãos.
- Passar uma cadeia de caracteres para append() insere texto sem analisar HTML.
- Inserir um nó existente o move em vez de copiá-lo.
- Crie um novo item dentro de cada passagem do laço quando precisar de vários objetos.
- appendChild() aceita um nó e o retorna; append() aceita várias entradas e retorna undefined.
- insertAdjacentHTML() preserva os filhos existentes, mas ainda analisa sua entrada como HTML.
5.2 Remover, substituir e clonar os objetos certos
Remover um elemento altera a árvore, mas não apaga todas as referências a esse objeto. Substituí-lo cria uma distinção semelhante: o novo objeto ocupa seu lugar, enquanto variáveis salvas ainda podem se referir ao antigo.
Remova um elemento ou várias correspondências
element.remove() desconecta esse elemento. parent.removeChild(child) é a forma mais antiga baseada no pai e retorna o nó removido. Se uma variável ainda contiver o nó, o script poderá lê-lo ou inseri-lo novamente mais tarde.
Para remover tarefas concluídas, selecione uma coleção estática e percorra-a:
document.querySelectorAll(".task.done")
.forEach(task => task.remove());
Com cinco tarefas, duas marcadas como concluídas, restam três. Remover um elemento não altera as referências mantidas pela NodeList estática, portanto o laço visita as duas tarefas selecionadas.
Não conte em ordem crescente em uma lista dinâmica que diminui
list.children é dinâmica. Com seis filhos, um laço em ordem crescente que remove items[i] remove apenas três. Após a primeira remoção, o segundo elemento é deslocado para o índice 0, mas i avança para 1. O próximo filho original é ignorado, e o mesmo deslocamento se repete.
Faça um retrato estático antes de remover todos os filhos atuais:
Array.from(list.children).forEach(item => item.remove());
Para simplesmente esvaziar um contêiner, list.replaceChildren() é mais claro. Definir list.textContent = "" ou list.innerHTML = "" também o esvazia. Uma cadeia de caracteres vazia não analisa conteúdo externo.
Substitua um único nó ou todo o conjunto de filhos
old.replaceWith(newElement) coloca um novo nó onde estava o antigo. Para <p id="status">Loading…</p>, document.querySelector("#status").replaceWith(list) substitui a mensagem pela lista. parent.replaceChildren(a, b, c) substitui todos os filhos do pai em uma operação, mantendo o próprio pai.
Essa diferença é importante para referências salvas. Uma variável que contém o pai continua válida após replaceChildren(), mas referências aos filhos removidos agora apontam para objetos desconectados. Substituir um contêiner com replaceWith() também desconecta esse contêiner.
Copie o elemento com ou sem descendentes
element.cloneNode(true) faz uma cópia profunda, incluindo descendentes e atributos. cloneNode() ou cloneNode(false) copia o elemento e seus atributos sem seus filhos. Um item de lista clonado sem descendentes não tem o texto do item original.
Um clone começa desconectado e precisa ser inserido. Ele também herda o id do original. Dê a ele um novo id ou remova esse atributo antes de colocá-lo na mesma página, para que a seleção por id continue confiável.
Trate elementos opcionais
Se uma pesquisa puder falhar, não chame imediatamente um método em seu resultado. document.querySelector("#promo").remove() lança um erro quando não existe uma promoção. document.querySelector("#promo")?.remove() não faz nada nesse caso. Para um contêiner obrigatório, um resultado ausente é um sinal útil para verificar o seletor e o momento de execução do script antes de tentar uma atualização estrutural.
Principais conclusões
- remove() desconecta um nó; uma referência salva ainda pode usá-lo ou reinseri-lo.
- Use uma lista estática ao remover vários elementos selecionados.
- replaceChildren() mantém o contêiner e substitui ou remove seus filhos.
- replaceWith() substitui o próprio nó selecionado.
- cloneNode(true) copia descendentes; um clone superficial os omite.
- A clonagem copia ids, portanto altere ou remova um id copiado antes da inserção.
6Transformar dados em uma página
Vetores descrevem o que uma página deve mostrar; a renderização transforma essas descrições em elementos. Comece com um item, amplie o padrão para listas e tabelas e depois organize marcações repetidas com fragmentos ou templates. Uma função de renderização torna previsíveis as atualizações posteriores quando os dados mudam. Mantenha distintos o vetor original, a visão selecionada e os elementos exibidos para que filtragem, ordenação, resultados vazios e resumos permaneçam consistentes.
6.1 Renderizar itens de um vetor como itens de lista e linhas de tabela
Renderização significa transformar dados em uma estrutura DOM visível. Mantenha o vetor como fonte e construa um elemento para cada objeto. Coloque os valores dos dados em textContent para que permaneçam como texto mesmo quando contiverem sinais de menor e maior.
Construa um elemento para cada objeto
Use estes objetos de livros:
const books = [
{ id: 1, title: "Dune", pages: 412 },
{ id: 2, title: "Emma", pages: 474 },
{ id: 3, title: "Beloved", pages: 324 }
];
function createBookItem(book) {
const li = document.createElement("li");
li.dataset.id = String(book.id);
li.textContent = `${book.title} (${book.pages} pages)`;
return li;
}
const list = document.querySelector("#books");
list.append(...books.map(createBookItem));
map() chama a função de construção uma vez por livro, produzindo três elementos separados. O espalhamento passa esses elementos como argumentos separados para append(). A exibição mostra “Dune (412 pages)”, “Emma (474 pages)” e “Beloved (324 pages)”. As quantidades de páginas somam 1.210.
Sem espalhamento, list.append(books.map(createBookItem)) recebe um único vetor. Ele transforma esse vetor em texto contendo cadeias como “[object HTMLLIElement]” em vez de inserir os elementos de item.
O id armazenado conecta o elemento exibido aos dados. Leia Number(li.dataset.id) antes de compará-lo com ids numéricos de livros e depois use books.find(book => book.id === id).
Trate dados ausentes e vazios
Se um campo opcional de autor estiver ausente, a interpolação direta exibirá “undefined”. Use book.author ?? "Unknown author" como alternativa quando o campo for null ou undefined. A coalescência nula mantém outros valores, incluindo 0 e uma cadeia de caracteres vazia, inalterados.
Se o vetor estiver vazio, exiba uma mensagem como “Nenhum livro ainda”. Um resultado vazio deve informar ao usuário que não há itens no momento. Ao renderizar novamente, substitua a exibição antiga para que uma mensagem ou itens anteriores não permaneçam junto ao novo resultado.
Saiba o que faz uma abordagem com cadeia HTML
Um vetor confiável pode ser mapeado para cadeias HTML, que são unidas com join("") antes da atribuição a innerHTML. A união remove as vírgulas que a conversão de vetor para cadeia de caracteres inseriria. Essa abordagem analisa cada valor interpolado como HTML. Use a abordagem de construção de elementos quando os valores puderem vir de fontes externas.
Construa uma estrutura de tabela válida
Para dados de tabela, construa um <tr> por objeto e um <td> para cada campo exibido. Acrescente as linhas ao <tbody> da tabela. Para medições de Oslo a 4,25 °C e do Cairo a 28,5 °C, a célula de temperatura pode usar reading.temp.toFixed(1): ela exibe “4.3” e “28.5”. toFixed() retorna uma cadeia de caracteres com as casas decimais solicitadas. Já toLocaleString() formata conforme a configuração regional do usuário, que pode usar vírgula decimal. Mantenha a formatação na etapa de exibição para que os dados numéricos continuem disponíveis para cálculos.
Construa as duas células antes de inserir a linha
Para um corpo de tabela vazio existente chamado tbody, isto renderiza as medições:
const readings = [{ city: "Oslo", temp: 4.25 }, { city: "Cairo", temp: 28.5 }];
const rows = readings.map(reading => {
const row = document.createElement("tr");
const city = document.createElement("td");
const temperature = document.createElement("td");
city.textContent = reading.city;
temperature.textContent = reading.temp.toFixed(1) + " °C";
row.append(city, temperature);
return row;
});
tbody.replaceChildren(...rows);
Cada passagem cria uma nova linha e duas novas células. Preencher as duas células antes de acrescentar a linha mantém explícita a ordem dos campos. Espalhar rows fornece os dois nós de linha separadamente; a substituição final também remove quaisquer linhas anteriores.
Principais conclusões
- Construa um elemento separado para cada objeto de dados e preencha os valores com textContent.
- Espalhe um vetor de nós ao passá-los para append().
- Use atributos de dados para conectar elementos exibidos a objetos.
- Forneça mensagens de estado vazio e alternativas para valores nulos ou indefinidos.
- Coloque linhas de tabela em tbody e campos em células.
- toFixed() retorna texto para exibição; mantenha os dados numéricos para cálculos.
6.2 Montar conteúdo repetido antes da inserção
Quando uma lista contém muitos itens, construa o novo conteúdo fora da página e insira-o de uma vez. Um fragmento de documento agrupa nós sem adicionar um elemento envoltório. Um template permite escrever uma estrutura repetida em HTML e preencher uma nova cópia para cada objeto.
Reúna nós em um fragmento
const fragment = document.createDocumentFragment();
for (const book of books) {
fragment.append(createBookItem(book));
}
list.append(fragment);
O fragmento começa fora do documento. Cada novo item se torna seu filho. Acrescentar o fragmento move seus filhos para a lista na ordem existente; não insere o próprio fragmento como envoltório. Depois que 100 itens são transferidos para uma lista vazia, a lista tem 100 filhos e o fragmento tem 0.
Esse padrão agrupa a inserção e mantém o código de construção organizado. Ele não promete um ganho específico de velocidade. Um vetor de nós construídos também funciona: list.append(...items) os adiciona, enquanto list.replaceChildren(...items) substitui o conteúdo atual por eles.
Defina marcação repetida em um template
<template id="book-row">
<li class="book"><span class="title"></span>
(<span class="pages"></span> pages)</li>
</template>
O navegador analisa essa marcação sem exibi-la. O conteúdo fica em um DocumentFragment separado em template.content. Uma pesquisa no nível do documento não pesquisa dentro desse fragmento. Selecione o template, clone seu conteúdo e depois pesquise dentro do clone:
const template = document.querySelector("#book-row");
const clone = template.content.cloneNode(true);
clone.querySelector(".title").textContent = book.title;
clone.querySelector(".pages").textContent = book.pages;
const item = clone.firstElementChild;
list.append(clone);
O título e a quantidade de páginas são preenchidos antes da inserção. item salva uma referência ao novo <li>. Após a inserção, clone está vazio porque seus filhos foram movidos, mas item ainda se refere ao elemento inserido.
Preserve a fonte reutilizável
Acrescente uma cópia a cada vez. Chamar list.append(template.content) move os nós de origem para fora do template. Uma pesquisa posterior dentro de template.content retorna então null, e a próxima tentativa de preencher o título ausente lança um erro. O template original deve permanecer disponível para livros posteriores.
Para muitas cópias, preencha cada fragmento clonado, acrescente essas cópias a um fragmento de agrupamento e depois insira a coleção. Um fragmento pode receber os filhos de outro fragmento, assim como uma lista pode.
Escolha um método de construção legível
createElement() é adequado para uma estrutura pequena ou que varia bastante conforme o item. Um template é adequado para uma marcação repetida maior que seja mais fácil de editar como HTML. Em ambos os casos, insira valores externos como texto. Uma cadeia HTML é adequada para marcação confiável, mas a interpolação nela ainda provoca análise de HTML. Selecione o método de construção com base na estrutura que você precisa manter, preservando a mesma ordem de criar ou clonar, preencher e inserir.
Reúna cópias preenchidas para uma substituição
Usando o template de livro acima e um vetor books existente:
const group = document.createDocumentFragment();
for (const book of books) {
const copy = template.content.cloneNode(true);
copy.querySelector(".title").textContent = book.title;
copy.querySelector(".pages").textContent = book.pages;
group.append(copy);
}
list.replaceChildren(group);
Cada cópia preenchida transfere seu item para group. A última linha substitui o conteúdo da lista por esses itens e esvazia group. O template original permanece intacto durante todo o processo, portanto a função pode repetir a construção para um vetor posterior.
Principais conclusões
- Acrescentar um fragmento move seus filhos e deixa o fragmento vazio.
- Um fragmento agrupa nós sem criar um envoltório na página.
- O conteúdo de um template é analisado, mas fica fora da árvore do documento exibido.
- Clone template.content para cada item e preencha-o antes da inserção.
- Salve a referência ao item antes que o fragmento que o contém seja esvaziado.
6.3 Manter as visões renderizadas sincronizadas com os dados
Use os dados como única fonte de verdade. Uma função de renderização deriva uma exibição do vetor atual. Chame-a após alterar o vetor ou um objeto nele contido.
Substitua a exibição a cada renderização
Suponha que tasks contenha quatro objetos, exatamente um concluído, e que a tarefa 2 exista e não esteja concluída. Uma função de renderização pode construir novos itens e um resumo:
function render() {
const items = tasks.map(task => {
const li = document.createElement("li");
li.dataset.id = String(task.id);
li.textContent = task.text;
li.classList.toggle("done", task.done);
return li;
});
list.replaceChildren(...items);
const doneCount = tasks.filter(task => task.done).length;
summary.textContent = `${doneCount} of ${tasks.length} done`;
}
Após tasks.push({ id: 5, text: "Book dentist", done: false }); render();, a lista tem cinco itens e o resumo diz “1 of 5 done”. Definir tasks.find(task => task.id === 2).done = true; render(); muda o resumo para “2 of 5 done”.
Substituir os filhos é essencial aqui. Se a função apenas acrescentasse todos os itens, chamá-la duas vezes duplicaria a exibição. Remover apenas um item do DOM também é temporário: se seu objeto permanecer no vetor, a renderização o trará de volta. Com tasks declarada usando let, exclua-o dos dados com tasks = tasks.filter(task => task.id !== id) e renderize novamente.
Derive uma visão sem perder a fonte
Para uma função de renderização que aceita um vetor de visão, passe tasks.filter(task => !task.done) para exibir apenas tarefas não concluídas. Mantenha o vetor completo para visões posteriores e contagens da lista inteira. Dê significados claros aos resumos: uma contagem de tarefas visíveis é diferente de uma contagem de todas as tarefas.
sort() altera o vetor no qual é chamado. Ordene uma cópia para exibição com [...tasks].sort(...) ou use tasks.toSorted(...) para obter uma cópia ordenada. Forneça um comparador: valores numéricos precisam de (a, b) => a - b, e títulos podem usar (a, b) => a.title.localeCompare(b.title). A ordenação padrão compara as formas de cadeia de caracteres, portanto [100, 25, 3].sort() permanece nessa ordem; a ordenação numérica fornece [3, 25, 100].
Associe ids e analise dados corretamente
Um dataset.id exibido é uma cadeia de caracteres. Converta-o antes da comparação estrita com ids numéricos, ou find() poderá retornar undefined mesmo quando o objeto desejado existir. Dados JSON são diferentes: JSON.parse() preserva números e booleanos JSON nesses tipos. Objetos analisados podem passar pela mesma função de renderização que objetos escritos diretamente no código.
Preserve o estado local quando necessário
Uma reconstrução completa cria novos elementos. Ela pode causar a perda do foco e do texto digitado em campos dentro da área reconstruída. Para uma pequena alteração de estado que precise preservar esses objetos, atualize os dados e depois atualize o item existente, como em li.classList.toggle("done", task.done). Os dados ainda precisam registrar a alteração para que uma renderização completa posterior corresponda à exibição atual.
Forneça entradas separadas para a visão e o resumo
Uma visão filtrada ainda pode mostrar um resumo de todas as tarefas:
function renderOpenTasks() {
const visible = tasks.filter(task => !task.done);
const nodes = visible.map(task => {
const li = document.createElement("li");
li.textContent = task.text;
return li;
});
if (visible.length === 0) {
const empty = document.createElement("li");
empty.textContent = "No open tasks";
nodes.push(empty);
}
list.replaceChildren(...nodes);
const done = tasks.filter(task => task.done).length;
summary.textContent = `${done} of ${tasks.length} done`;
}
Um vetor em que todas as tarefas estão concluídas exibe a mensagem de estado vazio para essa visão, mas mantém todos os objetos para o total. Contar a partir de visible responderia a outra pergunta e poderia indicar que não há tarefas concluídas simplesmente porque essa visão as exclui.
Principais conclusões
- Atualize os dados e depois derive a página a partir deles.
- Substitua os filhos antigos ao reconstruir uma lista para evitar duplicações.
- Filtre e ordene uma visão derivada, preservando o vetor original quando necessário.
- Forneça um comparador para ordenação numérica e converta ids de dataset antes da comparação numérica.
- JSON.parse() preserva os tipos de dados numérico e booleano.
- Use uma atualização pontual do elemento quando a reconstrução causaria perda de foco ou de estado necessário de um campo.
Exercícios resolvidos de DOM em JavaScript
1Localizar-se na árvore de uma página
11 passos
- 1IntroduçãoComece com uma página que você possa inspecionar
O navegador constrói objetos a partir do HTML. JavaScript trabalha com essa árvore DOM.
Acompanhe uma lista de dois itens desde a marcação até os nós e depois use relações familiares para alcançar um item próximo. Mantenha as DevTools abertas para comparar a página visível com sua árvore.
- 2ExplicaçãoEntre pela propriedade document
O DOM é o modelo dinâmico da página mantido pelo navegador.
documentfornece acesso;document.bodyrefere-se ao elemento do corpo.O navegador fornece essa API. JavaScript a chama para alterar a página atual sem recarregar ou reescrever o arquivo HTML do servidor.
- 3ExemploVeja o elemento e seu texto separadamente
Observe
<li>Buy milk</li>. O<li>se torna um nó de elemento, e “Buy milk” se torna um nó de texto filho dentro dele.Leia
nodeTypepara distingui-los: o elemento é do tipo 1 e seu filho de texto é do tipo 3. Comentários são do tipo 8, e o próprio documento é do tipo 9. “Nó” nomeia o grupo mais amplo; um elemento é um tipo de nó. - 4ExemploConte o que a indentação adiciona
Use exatamente esta disposição:
<ul id="tasks"> <li>Buy milk</li> <li>Call Sam</li> </ul>A lista tem dois elementos filhos. Ela também tem três nós de texto com espaços em branco: antes, entre e depois desses itens. Seu
children.lengthé, portanto, 2, enquantochildNodes.lengthé 5. Os nós adicionais vêm dos caracteres entre as tags. - 5DesafioPreveja o primeiro nó
Na lista indentada do slide anterior, que tipo de nó é
tasks.firstChilde por que ele é diferente detasks.firstElementChild?---reveal---
firstChildé o nó de texto com espaços em branco antes do primeiro item.firstElementChildignora esse nó e retorna o primeiro<li>. A indentação afeta a sequência de nós mesmo sem criar outra tarefa visível. - 6DicaInspecione a árvore atual
Escolha “Inspecionar” no primeiro item da lista. O painel Elementos mostra o DOM atual. Com o item selecionado,
$0no Console refere-se a ele, econsole.dir($0)mostra suas propriedades.A árvore pode incluir elementos adicionados pelo analisador, como um
<tbody>em torno de linhas de tabela. Use esse painel para verificar o aninhamento real em vez de presumir que ele corresponde a cada limite de tag no código-fonte. - 7ExemploVá para o próximo elemento
Salve a lista como
taskse depois siga uma relação entre elementos:const first = tasks.firstElementChild; const second = first.nextElementSibling;second.textContenté “Call Sam”. Lerfirst.nextSiblingem vez disso alcança os espaços em branco entre os itens. Escolha a forma para elementos quando a tarefa for navegar entre elementos da página e os nós de texto devam ser ignorados. - 8ExplicaçãoPare com segurança no último item
O
nextElementSiblingdo último item énull. Ler uma propriedade diretamente dessa referência ausente lança um erro de tipo.second.nextElementSibling?.textContentpara nesse ponto e forneceundefined, sem adicionar um nó ou fornecer uma cadeia de caracteres vazia. - 9ConexãoEncontre o item que contém o elemento pelo seu significado
Um span aninhado pode encontrar a tarefa que o contém com
span.closest("li"). A pesquisa começa no próprio span e depois verifica ancestrais sucessivos até encontrar uma correspondência.span.matches("li")testa apenas o span, retornando falso nesse caso. Uma pesquisa por ancestrais é útil quando um envoltório extra poderia fazer um número fixo de passos pelos pais levar ao lugar errado. - 10DesafioNavegue por um envoltório adicionado
Cada item da lista agora envolve seu texto em um span. Começando pelo primeiro span, como você pode ler o texto do próximo item sem depender de nós de espaços em branco ou do número de envoltórios dentro de um item?
---reveal---
Encontre o item que contém o span e depois seu próximo irmão que é elemento:
span.closest("li").nextElementSibling?.textContent. O item que contém o span é encontrado por sua tag, e a navegação apenas por elementos irmãos ignora os espaços em branco entre os itens. - 11RecapitulaçãoExperimente uma tabela em seguida
Inspecione uma tabela cujo código-fonte coloca uma linha diretamente dentro de
<table>. Encontre o pai real da linha.Compare suas contagens de nós filhos e elementos filhos, usando o painel Elementos para explicar a estrutura adicionada pelo analisador e os espaços em branco.
2Selecionar e atualizar os elementos desejados
12 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoEscolha uma pesquisa antes de alterar uma página
- 2ExplicaçãoUse a sintaxe de id adequada ao método
- 3ExemploMantenha uma classe repetida dentro de seu cartão
- 4DicaDistinga um nó ausente de uma sintaxe incorreta
- 5DesafioExplique um resultado null obtido cedo demais
- 6ExemploPercorra os elementos retornados
- 7ExplicaçãoConverta quando precisar de métodos de vetor
- 8ExemploCompare duas coleções salvas
- 9Ideia-chaveObserve uma coleção dinâmica que diminui
- 10DesafioEscolha o seletor combinado correto
- 11DesafioCombine escopo com iteração segura
- 12RecapitulaçãoInvestigue sua próxima pesquisa que falhar
3Atualizar um perfil e ler seus valores de formulário
15 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoSepare as informações que um elemento contém
- 2ExemploLeia texto sem suas tags
- 3ExplicaçãoTrate valores externos como caracteres
- 4DesafioPreserve um campo existente
- 5ConexãoEscolha a leitura do texto renderizado quando necessário
- 6ExemploLeia uma URL escrita ou uma URL resolvida
- 7ExplicaçãoDefina um booleano pela presença
- 8DesafioCorrija um controle desabilitado
- 9ExemploTransforme um nome de dados em um nome de propriedade
- 10ExplicaçãoLeia o conteúdo atual de um campo
- 11DesafioCalcule com o valor de um campo
- 12ExemploEncontre um objeto usando um id exibido
- 13DicaDê um nome legível a um controle com ícone
- 14DesafioConecte a busca de dados à exibição segura
- 15RecapitulaçãoInspecione um campo antes e depois da edição
4Fazer a aparência seguir um estado claro
13 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoDeixe que os dados determinem o estado visível
- 2ExemploMantenha uma classe básica ao adicionar um estado
- 3ExplicaçãoUse uma condição para atualizações repetidas
- 4DesafioPreveja duas atualizações repetidas
- 5ExemploCalcule uma porcentagem CSS
- 6ExplicaçãoLeia o resultado da cascata
- 7DesafioRestaure a cor da folha de estilos
- 8ExplicaçãoEscolha o que um painel fechado remove
- 9ExemploFaça um painel e seu controle concordarem
- 10DicaVerifique um estilo que sobrepõe hidden
- 11DesafioInvestigue um controle invisível, mas ativo
- 12DesafioCombine classes com um valor calculado
- 13RecapitulaçãoVerifique estado e aparência separadamente
5Construir itens e acompanhar suas referências a objetos
12 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoConstrua um item de tarefa em etapas separadas
- 2ExemploCrie um item desconectado
- 3ExemploInsira o item pronto
- 4ExplicaçãoEscolha entre filhos e irmãos
- 5ExemploMova um nó que já existe
- 6DesafioExplique um laço que resulta em um item
- 7ExplicaçãoDesconecte sem destruir uma referência
- 8ExemploSubstitua um item ou uma exibição inteira
- 9DicaCopie descendentes e verifique ids
- 10DesafioPreveja uma cópia superficial
- 11DesafioMova o original e insira uma cópia
- 12RecapitulaçãoAcompanhe identidades junto com a marcação
6Renderizar uma lista a partir de dados e atualizá-la de forma confiável
17 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoFaça o vetor orientar a exibição
- 2ExemploEscreva uma função de construção para um livro
- 3ExemploExpanda o vetor em argumentos de nós
- 4DicaMantenha dados ausentes legíveis
- 5ConexãoAplique o padrão a linhas de tabela
- 6DesafioDescubra por que a lista mostra texto de objeto
- 7ExemploReúna nós fora da página
- 8ExplicaçãoMantenha a estrutura repetida em HTML
- 9ExemploPreencha antes de transferir o clone
- 10DesafioPreserve o template reutilizável
- 11ExplicaçãoSubstitua a exibição a partir dos dados atuais
- 12ExemploAtualize um objeto e seu resumo
- 13ExplicaçãoMantenha uma visão ordenada separada
- 14DesafioExplique um item que retorna após a exclusão
- 15Ideia-chavePreserve o estado local de um campo
- 16DesafioCombine uma busca com uma atualização pontual
- 17RecapitulaçãoExecute uma verificação de renderização em três estados
Questões de DOM em JavaScript
Conjunto 1: Rastrear nós, estado e coleções10 Questões de Prática
Questão 1 de 10
insertAdjacentHTML() deve inserir uma nota confiável como primeiro filho da seção?Mostrar respostaOcultar resposta
afterbegin significa dentro do elemento, antes de seus filhos atuais, portanto a nota se torna o primeiro filho da seção. beforebegin faria da nota um elemento irmão fora da seção. Os nomes begin e end descrevem os limites do elemento, e a parte before ou after determina qual lado do limite é usado.Questão 2 de 10
Mostrar respostaOcultar resposta
removeProperty("color") remove apenas a declaração de cor em linha e preserva a largura em linha. Limpar todo o atributo style ou cssText removeria ambos. Atribuir “inherit” mantém uma regra de cor em linha e usa explicitamente a cor do pai, o que é diferente de remover a sobrescrita.Questão 3 de 10
entry e está dentro de uma seção com essa mesma classe. O que button.closest(".entry") retorna?Mostrar respostaOcultar resposta
closest() verifica o próprio botão antes de seus ancestrais, portanto retorna o botão correspondente. Ele só alcança a seção se o botão não corresponder; duas correspondências no caminho não causam erro.Questão 4 de 10
.mark. O código salva uma coleção dinâmica por classe e uma NodeList estática correspondente. Ele remove o primeiro membro da coleção dinâmica e depois remove a classe do novo primeiro membro dessa coleção. Quais são os tamanhos finais das coleções dinâmica e estática?Mostrar respostaOcultar resposta
Questão 5 de 10
Mostrar respostaOcultar resposta
counter.textContent + 1 é tarde demais: essa expressão já concatenou as cadeias e produziu “121”. A ordem da conversão e da adição determina o resultado.Questão 6 de 10
https://example.com/catalog/, um link é escrito como <a href="/guide">Guide</a>. O que link.getAttribute("href") retorna?Mostrar respostaOcultar resposta
Questão 7 de 10
class="row done". O código executa row.classList.toggle("done", false) duas vezes. Quais classes permanecem?Mostrar respostaOcultar resposta
Questão 8 de 10
Mostrar respostaOcultar resposta
Questão 9 de 10
template.content diretamente a uma lista. Por que uma chamada posterior a template.content.querySelector(".title") retorna null?Mostrar respostaOcultar resposta
Questão 10 de 10
[{id:31, done:true}, {id:32, done:false}, {id:33, done:false}]. O código remove apenas a linha 31 do DOM, marca a tarefa 32 como concluída no vetor e depois reconstrói todas as linhas e o resumo a partir desse vetor. O que é exibido?Mostrar respostaOcultar resposta
Conjunto 2: Ler e alterar uma página10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
<ul><li>A</li> <li>B</li></ul>, uma variável first contém o primeiro item. O que first.nextSibling.nodeType retorna?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
<section id="report"> com getElementById()?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
flag. O código salva const live = box.getElementsByClassName("flag") e depois executa for (let i = 0; i < live.length; i++) { live[i].classList.remove("flag"); }. Quais elementos mantêm a classe?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
label.textContent = "<em>Saved</em>"?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
button.setAttribute("disabled", "false"). Que estado button.disabled informa?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
input.value + 2 produz?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
class="card compact". Como o código pode adicionar “selected” e preservar as duas classes existentes?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
list.append(list.firstElementChild)?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
makeItem() retorna um novo <li>. O que list.append(records.map(makeItem)) insere quando records tem duas entradas?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 3: Escolher a operação DOM correta10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
data-record-id="38". Como o código pode comparar esse id com o número 38 usando igualdade estrita?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
<head> seleciona um rodapé escrito mais adiante em <body> e obtém null. O seletor está correto. Qual atributo de script faz com que ele seja executado após a análise do HTML?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
.note. Um perde sua classe note, e um novo elemento note é acrescentado. Qual é o tamanho da NodeList salva?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
<table><tr><td>8</td></tr></table>. Qual elemento filho direto o analisador normalmente coloca dentro da tabela?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
container.replaceChildren(), define a.textContent = "C" e depois executa container.append(a) e container.append(a.cloneNode(true)). O que o contêiner contém?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
score: 0. O que record.score ?? "Pending" exibe quando atribuído a textContent?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
[{n: 14}, {n: 3}, {n: 9}]. Uma visão deve mostrar a ordem numérica crescente e preservar a ordem de origem. Qual expressão constrói essa visão?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 4: Construir exibições confiáveis a partir de dados10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
a, executa list.lastElementChild.before(a) e depois list.prepend(list.lastElementChild). Qual é a ordem final?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
Hello, um <strong>team</strong> aninhado e um comentário HTML. O texto do elemento strong é irmão do comentário?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
.status. Uma variável main contém a seção principal. Qual pesquisa encontra seu primeiro descendente status?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
const field = box.querySelector("input"). Um usuário altera esse input de “A” para “B”. O script executa box.innerHTML += "<span>Done</span>" e depois field.value = "C". O que acontece com o input visível?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
value="2". Depois que o usuário o altera para 7, um script lê Number(input.getAttribute("value")) + 1. Que número ele obtém?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
panel.hidden = true, mas o CSS contém .panel { display: grid; } e o painel permanece visível. Seu controle também continua informando aria-expanded="true". O que corrige os dois estados para um painel fechado?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
author. Qual atribuição exibe “Unknown author” sem analisar o valor como HTML?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
clone.querySelector(".name").textContent = record.name. Por que isso falha?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
<li> do id 12 e depois renderiza uma visão filtrada a partir do vetor inalterado. O filtro mantém os três objetos. O que deve mudar para que o id 12 permaneça excluído após qualquer renderização completa posterior?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
[{"id":24,"done":false}]. Após JSON.parse(), como os tipos de id e done se comparam ao data-id="24" de um elemento?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 5: Depurar atualizações no DOM10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
<div class="card"><div class="body"><span class="label">A</span></div></div>. A partir do rótulo, o código usa parentElement.parentElement para encontrar o cartão. Um novo envoltório é inserido entre body e label. Qual substituição continua confiável?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
snap = list.querySelectorAll(".new"). Dois elementos com a classe new são acrescentados, e depois um laço sobre snap remove a classe new. Uma nova pesquisa por classe é salva como coleção dinâmica. Quais são snap.length e o tamanho da coleção dinâmica?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
<script>. Qual atualização mantém o elemento de prévia e insere o comentário como texto literal, sem análise de HTML?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
class="row selected". Os dados dizem que selected é falso. O código executa row.classList.toggle("selected") e depois executa row.classList.toggle("selected", false). Quais são os dois valores de retorno e as classes finais?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
const open = panel.hidden, define panel.hidden = !open e escreve String(open) em aria-expanded. Quais são os estados finais?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
<li id="copy-me"><span>Map</span></li> é copiado com cloneNode(false). O que o clone desconectado contém?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
list.replaceChildren(fragment). Quais objetos permanecem preenchidos?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
{id: 5, done: false}. Sua linha existente tem data-id="5" e um campo com foco. O código deve marcar o registro como concluído, refletir isso na classe e preservar o objeto do campo. Qual sequência é adequada?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Travou em uma questão sua? Ajuda com Tarefas
Termos-Chave
A
Alternância de classe com estado forçado
row.classList.toggle("done", task.done) mantém a linha consistente em renderizações repetidas.Análise sintática
<tbody>.Atributo
getAttribute() e setAttribute().href de um link pode conter “/help”, enquanto sua propriedade informa uma URL completa resolvida.Atributo ARIA
aria-label como “Close dialog” fornece um nome acessível para um botão que contém apenas um ícone.Atributo aria-expanded
aria-expanded="true".Atributo booleano
setAttribute("disabled", "false") porque o atributo existe.Atributo de dados
data- e armazena informações para scripts sem exibi-las como texto.data-id="26" pode ser associada ao objeto que forneceu seus campos exibidos.Atributo defer
Atualização pontual
C
Clone profundo
Coalescência nula
?? apenas quando o valor à esquerda é null ou undefined, mantendo os demais valores inalterados.book.author ?? "Unknown author" fornece texto legível quando o autor opcional está ausente.Coleção dinâmica
Coleção estática
querySelectorAll() omite um quarto item acrescentado após a pesquisa original.Coleção HTMLCollection
list.children.Coleção NodeList
querySelectorAll() contém elementos correspondentes.Array.from() antes de usar o método de vetor map().Comparador
(a, b) => a - b ordena valores numéricos do menor para o maior.Conteúdo do elemento template
template.content, que contém a estrutura filha não exibida do template.Conversão de tipos
Number(row.dataset.id) permite que a igualdade estrita compare os algarismos armazenados com o id numérico de um objeto.Corpo da tabela
<tbody> que agrupa as linhas de dados de uma tabela.<tr> ao corpo selecionado e preenche seus campos em células <td>.D
Declaração display: none
Declaração opacity: 0
Declaração visibility: hidden
E
Elemento
<ul> pode conter dois elementos filhos <li>, além de nós de texto com espaços em branco.Elemento template
Estado vazio
Estilo computado
getComputedStyle(title).color pode informar vermelho mesmo quando title.style.color está vazio.Estilo em linha (inline)
bar.style.width = "60%" armazena uma largura de progresso calculada diretamente na barra.F
Ferramentas de desenvolvimento (DevTools)
$0 no Console.Fonte de verdade
Fragmento de documento (DocumentFragment)
Função de renderização
I
Injeção de scripts entre sites (XSS)
textContent para um nome enviado impede que seus caracteres se tornem marcação injetada.Inserção em lote
replaceChildren(...items).M
Método append()
item.append(title, button) monta dois elementos filhos dentro de um item antes de sua inserção na página.Método Array.from()
Array.from(list.children) permite que um laço de remoção visite cada filho original sem deslocamentos de índice.Método closest()
closest(".product") para encontrar o cartão que o contém.Método createElement()
document.createElement("li") cria um item de lista, mas ainda não o adiciona à lista visível.Método getElementById()
document.getElementById("result") procura o id “result”, sem uma cerquilha inicial.Método insertAdjacentHTML()
Método insertBefore()
list.insertBefore(newItem, list.firstElementChild) coloca o item antes do primeiro elemento filho.Método prepend()
Método querySelector()
null se nenhum corresponder..name repetida em outro lugar se torne o resultado.Método replaceChildren()
Método replaceWith()
Método toFixed()
toFixed(1) antes da inserção em uma célula.Modelo de Objetos do Documento (DOM)
N
Nó
Nó ancestral
Nó de texto
Nó desconectado
Nó filho
Nó irmão
Nó pai
<ul><li>Read</li></ul>, a lista é o pai imediato do elemento de item.Nome individual de classe
classList.add() para que nenhum dos nomes contenha espaço.Notação camelCase
backgroundColor.background-color é escrita como style.backgroundColor em JavaScript.O
Ordenação no próprio vetor (in-place)
[...items] antes de chamar sort() quando a ordem de origem precisar permanecer inalterada.P
Propriedade
disabled retorna um booleano, enquanto a leitura de um atributo retorna uma cadeia de caracteres ou null.Propriedade checked
checked torna-se falsa.Propriedade classList
classList mantém a classe “card” existente e seu estilo básico.Propriedade className
className de um cartão remove sua antiga classe “card”, a menos que ela seja incluída novamente.Propriedade dataset
row.dataset.recordId = "26" cria ou altera o atributo data-record-id.Propriedade hidden
panel.hidden = false para revelar um painel que foi ocultado sem reconstruir seu conteúdo.Propriedade innerHTML
"<strong>Ready</strong>" cria um novo elemento strong dentro do contêiner.Propriedade innerText
innerText de um rótulo visível omite uma nota aninhada com o estilo display: none.Propriedade outerHTML
Propriedade personalizada CSS
var()."--accent" por meio de style.setProperty() para alterar regras que fazem referência ao valor de destaque.Propriedade textContent
Propriedade value
R
Renderização
S
Seletor CSS
"#profile .name" encontra descendentes com a classe name do elemento de perfil.Sintaxe de espalhamento (spread)
list.append(...items) insere cada nó construído em vez da representação do vetor como cadeia de caracteres.U
Unidade CSS
V
Valor nulo (null)
Visão derivada
tasks.filter(task => !task.done) sem descartar as concluídas.Sobre esta aula
Crie seus próprios Materiais de Estudo
Transforme suas anotações, slides e documentos em Guias de Estudo, Questões de Prática, Flashcards e mais 6 ferramentas.