DOM em JavaScript: o Modelo de Objetos do Documento

Use JavaScript para alterar uma página web enquanto ela está aberta. Aprenda como o navegador transforma HTML em uma árvore de objetos, selecione os elementos necessários e altere seus textos, atributos, classes e estilos. Crie, mova e remova elementos e transforme vetores de dados em listas e tabelas que acompanham os dados, tudo sem recarregar a página.

BásicoAula 5 de 9 do curso Curso de Programação em JavaScript

O que você vai aprender

  1. 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ós
      Explique 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ãos
      Percorra 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.
  2. 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 elemento
      Encontre 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 resultados
      Selecione todos os elementos correspondentes, percorra os resultados, converta-os em um vetor quando necessário e saiba quando uma coleção se atualiza sozinha.
  3. 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 elemento
      Leia 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 propriedades
      Trabalhe 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ário
      Mantenha informações extras nos elementos com atributos de dados e leia e defina o valor atual dos campos de formulário.
  4. 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 CSS
      Altere 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 computados
      Defina 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ágina
      Oculte 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.
  5. 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-los
      Crie 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 elementos
      Retire elementos da página, esvazie um contêiner, substitua um elemento por outro e faça cópias com cloneNode.
  6. 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 vetor
      Transforme 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 template
      Insira 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 mudarem
      Mantenha 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.

Guia de estudo de DOM em JavaScript

6 capítulos

1

Ler 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.
2

Encontrar 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.
3

Atualizar 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, ou null se 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.
4

Controlar 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.
5

Construir 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.
6

Transformar 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

6 Lições Interativas

1

Localizar-se na árvore de uma página

11 passos
Inspecione uma lista pequena, distinga elementos de texto e siga caminhos confiáveis até o conteúdo próximo.
  1. 1
    Introduçã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.

  2. 2
    ExplicaçãoEntre pela propriedade document

    O DOM é o modelo dinâmico da página mantido pelo navegador. document fornece acesso; document.body refere-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.

  3. 3
    ExemploVeja 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 nodeType para 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ó.

  4. 4
    ExemploConte 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, enquanto childNodes.length é 5. Os nós adicionais vêm dos caracteres entre as tags.

  5. 5
    DesafioPreveja o primeiro nó

    Na lista indentada do slide anterior, que tipo de nó é tasks.firstChild e por que ele é diferente de tasks.firstElementChild?

    ---reveal---

    firstChild é o nó de texto com espaços em branco antes do primeiro item. firstElementChild ignora esse nó e retorna o primeiro <li>. A indentação afeta a sequência de nós mesmo sem criar outra tarefa visível.

  6. 6
    DicaInspecione a árvore atual

    Escolha “Inspecionar” no primeiro item da lista. O painel Elementos mostra o DOM atual. Com o item selecionado, $0 no Console refere-se a ele, e console.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.

  7. 7
    ExemploVá para o próximo elemento

    Salve a lista como tasks e depois siga uma relação entre elementos:

    const first = tasks.firstElementChild;
    const second = first.nextElementSibling;
    

    second.textContent é “Call Sam”. Ler first.nextSibling em 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.

  8. 8
    ExplicaçãoPare com segurança no último item

    O nextElementSibling do último item é null. Ler uma propriedade diretamente dessa referência ausente lança um erro de tipo.

    second.nextElementSibling?.textContent para nesse ponto e fornece undefined, sem adicionar um nó ou fornecer uma cadeia de caracteres vazia.

  9. 9
    Conexã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.

  10. 10
    DesafioNavegue 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.

  11. 11
    Recapitulaçã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.

2

Selecionar e atualizar os elementos desejados

12 passos
Escolha o escopo da pesquisa, verifique resultados ausentes e evite surpresas em laços com coleções dinâmicas.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoEscolha uma pesquisa antes de alterar uma página
  2. 2
    ExplicaçãoUse a sintaxe de id adequada ao método
  3. 3
    ExemploMantenha uma classe repetida dentro de seu cartão
  4. 4
    DicaDistinga um nó ausente de uma sintaxe incorreta
  5. 5
    DesafioExplique um resultado null obtido cedo demais
  6. 6
    ExemploPercorra os elementos retornados
  7. 7
    ExplicaçãoConverta quando precisar de métodos de vetor
  8. 8
    ExemploCompare duas coleções salvas
  9. 9
    Ideia-chaveObserve uma coleção dinâmica que diminui
  10. 10
    DesafioEscolha o seletor combinado correto
  11. 11
    DesafioCombine escopo com iteração segura
  12. 12
    RecapitulaçãoInvestigue sua próxima pesquisa que falhar
3

Atualizar um perfil e ler seus valores de formulário

15 passos
Escolha texto simples, propriedades de elementos, atributos e entradas de dataset para diferentes tipos de informação.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoSepare as informações que um elemento contém
  2. 2
    ExemploLeia texto sem suas tags
  3. 3
    ExplicaçãoTrate valores externos como caracteres
  4. 4
    DesafioPreserve um campo existente
  5. 5
    ConexãoEscolha a leitura do texto renderizado quando necessário
  6. 6
    ExemploLeia uma URL escrita ou uma URL resolvida
  7. 7
    ExplicaçãoDefina um booleano pela presença
  8. 8
    DesafioCorrija um controle desabilitado
  9. 9
    ExemploTransforme um nome de dados em um nome de propriedade
  10. 10
    ExplicaçãoLeia o conteúdo atual de um campo
  11. 11
    DesafioCalcule com o valor de um campo
  12. 12
    ExemploEncontre um objeto usando um id exibido
  13. 13
    DicaDê um nome legível a um controle com ícone
  14. 14
    DesafioConecte a busca de dados à exibição segura
  15. 15
    RecapitulaçãoInspecione um campo antes e depois da edição
4

Fazer a aparência seguir um estado claro

13 passos
Alterne classes, calcule estilos de progresso e sincronize um painel com seu estado expandido acessível.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoDeixe que os dados determinem o estado visível
  2. 2
    ExemploMantenha uma classe básica ao adicionar um estado
  3. 3
    ExplicaçãoUse uma condição para atualizações repetidas
  4. 4
    DesafioPreveja duas atualizações repetidas
  5. 5
    ExemploCalcule uma porcentagem CSS
  6. 6
    ExplicaçãoLeia o resultado da cascata
  7. 7
    DesafioRestaure a cor da folha de estilos
  8. 8
    ExplicaçãoEscolha o que um painel fechado remove
  9. 9
    ExemploFaça um painel e seu controle concordarem
  10. 10
    DicaVerifique um estilo que sobrepõe hidden
  11. 11
    DesafioInvestigue um controle invisível, mas ativo
  12. 12
    DesafioCombine classes com um valor calculado
  13. 13
    RecapitulaçãoVerifique estado e aparência separadamente
5

Construir itens e acompanhar suas referências a objetos

12 passos
Crie e insira novo conteúdo, mova um item existente e depois remova e clone sem perder de vista a identidade.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoConstrua um item de tarefa em etapas separadas
  2. 2
    ExemploCrie um item desconectado
  3. 3
    ExemploInsira o item pronto
  4. 4
    ExplicaçãoEscolha entre filhos e irmãos
  5. 5
    ExemploMova um nó que já existe
  6. 6
    DesafioExplique um laço que resulta em um item
  7. 7
    ExplicaçãoDesconecte sem destruir uma referência
  8. 8
    ExemploSubstitua um item ou uma exibição inteira
  9. 9
    DicaCopie descendentes e verifique ids
  10. 10
    DesafioPreveja uma cópia superficial
  11. 11
    DesafioMova o original e insira uma cópia
  12. 12
    RecapitulaçãoAcompanhe identidades junto com a marcação
6

Renderizar uma lista a partir de dados e atualizá-la de forma confiável

17 passos
Construa itens repetidos, use um template com segurança e mantenha visões filtradas e resumos consistentes com os dados.

Salve esta aula para seguir cada Lição Interativa passo a passo.

  1. 1
    IntroduçãoFaça o vetor orientar a exibição
  2. 2
    ExemploEscreva uma função de construção para um livro
  3. 3
    ExemploExpanda o vetor em argumentos de nós
  4. 4
    DicaMantenha dados ausentes legíveis
  5. 5
    ConexãoAplique o padrão a linhas de tabela
  6. 6
    DesafioDescubra por que a lista mostra texto de objeto
  7. 7
    ExemploReúna nós fora da página
  8. 8
    ExplicaçãoMantenha a estrutura repetida em HTML
  9. 9
    ExemploPreencha antes de transferir o clone
  10. 10
    DesafioPreserve o template reutilizável
  11. 11
    ExplicaçãoSubstitua a exibição a partir dos dados atuais
  12. 12
    ExemploAtualize um objeto e seu resumo
  13. 13
    ExplicaçãoMantenha uma visão ordenada separada
  14. 14
    DesafioExplique um item que retorna após a exclusão
  15. 15
    Ideia-chavePreserve o estado local de um campo
  16. 16
    DesafioCombine uma busca com uma atualização pontual
  17. 17
    RecapitulaçãoExecute uma verificação de renderização em três estados

Questões de DOM em JavaScript

50 Questões de Prática em 5 conjuntos

Conjunto 1: Rastrear nós, estado e coleções10 Questões de Prática

Questão 1 de 10

Uma seção já contém dois parágrafos. Em qual posição insertAdjacentHTML() deve inserir uma nota confiável como primeiro filho da seção?
  1. "beforebegin"
  2. "afterbegin"
  3. "beforeend"
  4. "afterend"
Mostrar respostaOcultar resposta
Resposta: B
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

Uma caixa tem largura e cor em linha. Como o código pode remover apenas a cor em linha para que a folha de estilos a determine?
  1. box.style.cssText = ""
  2. box.removeAttribute("style")
  3. box.style.removeProperty("color")
  4. box.style.color = "inherit"
Mostrar respostaOcultar resposta
Resposta: C
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

Um botão tem a classe entry e está dentro de uma seção com essa mesma classe. O que button.closest(".entry") retorna?
  1. A seção externa.
  2. O elemento pai da seção.
  3. Null; ambos correspondem.
  4. O próprio botão.
Mostrar respostaOcultar resposta
Resposta: D
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

Uma caixa começa com quatro elementos .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?
  1. Dinâmica 2, estática 3.
  2. Dinâmica 3, estática 4.
  3. Dinâmica 2, estática 4.
  4. Dinâmica 3, estática 3.
Mostrar respostaOcultar resposta
Resposta: C
Remover o primeiro elemento reduz a coleção dinâmica a três. Remover a classe de seu novo primeiro membro a reduz a dois. A NodeList estática mantém as quatro referências originais, incluindo o nó desconectado; seus membros não acompanham a remoção nem uma alteração posterior na classe de um elemento selecionado.

Questão 5 de 10

Um contador exibe “12”. Qual atribuição faz com que ele exiba “13”?
  1. counter.textContent = Number(counter.textContent) + 1
  2. counter.textContent = counter.textContent + 1
  3. counter.textContent = counter.textContent + "1"
  4. counter.textContent = Number(counter.textContent + 1)
Mostrar respostaOcultar resposta
Resposta: A
Converta o texto original “12” no número 12 antes de somar 1 e depois atribua o resultado para exibição. Converter apenas após 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

Em https://example.com/catalog/, um link é escrito como <a href="/guide">Guide</a>. O que link.getAttribute("href") retorna?
  1. "https://example.com/guide"
  2. "/guide"
  3. "https://example.com/catalog/guide"
  4. "guide"
Mostrar respostaOcultar resposta
Resposta: B
A leitura do atributo retorna o texto literal “/guide”. Já a propriedade href o resolve como “https://example.com/guide”; uma barra inicial aponta a partir da raiz da origem, não do diretório catalog.

Questão 7 de 10

Uma linha começa com class="row done". O código executa row.classList.toggle("done", false) duas vezes. Quais classes permanecem?
  1. Apenas “row”.
  2. Tanto “row” quanto “done”.
  3. Apenas “done”.
  4. Nenhuma classe permanece.
Mostrar respostaOcultar resposta
Resposta: A
O segundo argumento força a ausência de “done”, portanto ambas as chamadas deixam apenas “row”. Uma alternância com um argumento inverteria o estado em cada chamada e restauraria “done” após a segunda. A alternância com estado forçado faz o DOM corresponder a uma condição conhecida, independentemente das chamadas anteriores.

Questão 8 de 10

Um item com id “entry” e um span aninhado é clonado profundamente. O id do clone é alterado para “entry-copy”, depois ele é acrescentado e o original é removido. Para onde aponta uma referência salva ao span original?
  1. Para o span correspondente dentro do clone acrescentado.
  2. Para o novo contêiner pai do item acrescentado.
  3. Para null, pois o item original foi removido.
  4. Para o span dentro do item original desconectado.
Mostrar respostaOcultar resposta
Resposta: D
A clonagem profunda cria objetos descendentes separados; ela não redireciona referências dos originais para as cópias. Remover o item original desconecta sua subárvore, portanto o span salvo permanece dentro desse item desconectado. A variável ainda contém um nó, não null, enquanto o clone tem seu próprio span separado.

Questão 9 de 10

O código acrescenta template.content diretamente a uma lista. Por que uma chamada posterior a template.content.querySelector(".title") retorna null?
  1. O template tornou-se uma cadeia HTML.
  2. A classe foi removida durante a inserção.
  3. O conteúdo de origem foi movido para a lista.
  4. O conteúdo do template rejeita seletores de classe.
Mostrar respostaOcultar resposta
Resposta: C
Acrescentar o fragmento move seus filhos para a lista e deixa o conteúdo do template vazio. A pesquisa posterior, portanto, não encontra um elemento de título ali. Clone o conteúdo antes de preencher e acrescentar cada item; a inserção não remove atributos de classe nem impede o funcionamento de seletores dentro de fragmentos.

Questão 10 de 10

As tarefas são [{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?
  1. Três linhas; “2 of 3 done”.
  2. Duas linhas; “1 of 2 done”.
  3. Três linhas; “1 of 3 done”.
  4. Duas linhas; “2 of 2 done”.
Mostrar respostaOcultar resposta
Resposta: A
A tarefa 31 permanece no vetor, portanto a reconstrução completa restaura sua linha. Marcar a tarefa 32 como concluída resulta em dois objetos concluídos de um total de três, produzindo “2 of 3 done”. Uma contagem de duas linhas trataria a remoção anterior apenas do DOM como se ela também tivesse excluído o objeto de origem.
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

Um script altera um parágrafo de “Rascunho” para “Pronto”. O que “Ver código-fonte da página” mostra para esse parágrafo após a alteração?
  1. O texto atualizado do DOM, “Pronto”.
  2. O texto original do HTML, “Rascunho”.
  3. Os dois textos como nós de texto adjacentes.
  4. Um parágrafo vazio após a edição.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Para <ul><li>A</li> <li>B</li></ul>, uma variável first contém o primeiro item. O que first.nextSibling.nodeType retorna?
  1. 1
  2. 8
  3. 9
  4. 3
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Como um script pode selecionar o elemento <section id="report"> com getElementById()?
  1. document.getElementById("report")
  2. document.getElementById("#report")
  3. document.getElementById("section#report")
  4. document.getElementById("[id=report]")
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Cinco elementos, na ordem de A a E, têm a classe 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?
  1. C e E.
  2. B, C e D.
  3. B e D.
  4. A, C e E.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

O que aparece após label.textContent = "<em>Saved</em>"?
  1. A palavra “Saved” em um elemento em.
  2. Um elemento em sem texto dentro.
  3. O texto literal “Saved”.
  4. O texto literal “Saved” sem tags.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Um botão está desabilitado. O código executa button.setAttribute("disabled", "false"). Que estado button.disabled informa?
  1. false
  2. true
  3. "false"
  4. null
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Um input contém atualmente “6”. O que input.value + 2 produz?
  1. "62"
  2. 8
  3. "8"
  4. 62
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Um cartão começa com class="card compact". Como o código pode adicionar “selected” e preservar as duas classes existentes?
  1. card.className = "selected"
  2. card.classList.add(".selected")
  3. card.setAttribute("class", "selected")
  4. card.classList.add("selected")
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Uma lista contém elementos identificados por P, Q, R. Qual é sua ordem após list.append(list.firstElementChild)?
  1. P, Q, R, P.
  2. Q, R, P.
  3. R, P, Q.
  4. P, R, Q.
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?
  1. Dois elementos li com o conteúdo construído.
  2. Um elemento li com os dois elementos construídos.
  3. Texto formado pelos dois objetos de elemento.
  4. Duas cópias dos registros como texto JSON.
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

Um elemento tem data-record-id="38". Como o código pode comparar esse id com o número 38 usando igualdade estrita?
  1. row.dataset.recordId === 38
  2. Number(row.getAttribute("record-id")) === 38
  3. row.dataset["record-id"] === 38
  4. Number(row.dataset.recordId) === 38
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Uma folha de estilos define a cor de um título, e o título não tem cor em linha. Como o código pode ler a cor aplicada?
  1. heading.style.color
  2. getComputedStyle(heading).color
  3. heading.getAttribute("color")
  4. heading.dataset.color
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Um painel fechado deve manter seu espaço no layout e ficar oculto dos leitores de tela. Qual declaração CSS é adequada?
  1. visibility: hidden
  2. display: none
  3. opacity: 0
  4. visibility: visible
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Um script externo clássico em <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?
  1. defer
  2. async
  3. disabled
  4. hidden
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Uma NodeList estática contém dois elementos .note. Um perde sua classe note, e um novo elemento note é acrescentado. Qual é o tamanho da NodeList salva?
  1. 1
  2. 2
  3. 3
  4. 0
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

O HTML contém <table><tr><td>8</td></tr></table>. Qual elemento filho direto o analisador normalmente coloca dentro da tabela?
  1. O tr exatamente como foi escrito.
  2. O td retirado de dentro da linha.
  3. Um tbody contendo a linha.
  4. Uma div envolvendo as células da tabela.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Um contêiner tem os itens A e B. O código salva seu primeiro item como a, chama 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?
  1. Um item mostrando “C”.
  2. Dois itens mostrando “A” e “C”.
  3. Dois itens mostrando ambos “C”.
  4. Três itens mostrando “A”, “B” e “C”.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Um registro tem score: 0. O que record.score ?? "Pending" exibe quando atribuído a textContent?
  1. “Pending”
  2. “undefined”
  3. Uma cadeia de caracteres vazia.
  4. “0”
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Uma lista vazia recebe um fragmento contendo três itens. O código altera então o textContent do fragmento para “Reset” e acrescenta o mesmo fragmento novamente. O que está na lista?
  1. Os três itens originais, seguidos do texto “Reset”.
  2. Apenas o texto “Reset”, substituindo os três itens.
  3. Seis itens, seguidos do texto “Reset”.
  4. Os três itens com todos os rótulos definidos como “Reset”.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Os dados são [{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?
  1. data.sort((a, b) => a.n - b.n)
  2. [...data].sort((a, b) => a.n - b.n)
  3. [...data].sort((a, b) => b.n - a.n)
  4. [...data].sort((a, b) => String(a.n).localeCompare(String(b.n)))
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

Uma lista começa com A, B, C. O código salva seu primeiro elemento como a, executa list.lastElementChild.before(a) e depois list.prepend(list.lastElementChild). Qual é a ordem final?
  1. B, A, C.
  2. C, B, A.
  3. C, A, B.
  4. A, C, B.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Um parágrafo contém Hello, um <strong>team</strong> aninhado e um comentário HTML. O texto do elemento strong é irmão do comentário?
  1. Sim; o parágrafo é seu pai.
  2. Não; seu texto é filho de strong.
  3. Sim; comentários são irmãos de todo o texto.
  4. Não; esse texto é um atributo.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Uma página tem uma barra lateral e uma seção principal, cada uma com .status. Uma variável main contém a seção principal. Qual pesquisa encontra seu primeiro descendente status?
  1. document.querySelector(".status")
  2. main.getElementById("status")
  3. main.querySelector(".status")
  4. document.getElementById(".status")
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

O código salva 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?
  1. É um input substituto; a última atribuição altera apenas o original desconectado.
  2. É o input original e agora exibe o valor final “C”.
  3. É o input substituto, e a referência salva passa a apontar para ele.
  4. É removido permanentemente porque innerHTML não consegue reconstruir inputs.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Um input começa com 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?
  1. 8
  2. 21
  3. 71
  4. 3
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Um painel é ocultado com 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?
  1. Manter a regra display e definir aria-expanded como “false” sem alterar o CSS.
  2. Definir a opacidade como zero e manter o valor atual de aria-expanded.
  3. Remover hidden e definir aria-expanded como “true” para corresponder ao layout atual.
  4. Garantir a aplicação de [hidden] { display: none !important; } e definir aria-expanded como “false”.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Um registro não tem a propriedade author. Qual atribuição exibe “Unknown author” sem analisar o valor como HTML?
  1. cell.textContent = record.author ?? "Unknown author"
  2. cell.textContent = String(record.author)
  3. cell.innerHTML = record.author ?? "Unknown author"
  4. cell.textContent = record.author === null ? "Unknown author" : record.author
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Uma função de renderização clona um template de uma linha, acrescenta o clone a um fragmento e só então tenta clone.querySelector(".name").textContent = record.name. Por que isso falha?
  1. Um fragmento não pode conter filhos de outro fragmento.
  2. A clonagem profunda remove classes dos campos clonados.
  3. A inserção esvaziou o clone antes de seu campo ser preenchido.
  4. Um campo de template não aceita textContent antes da exibição.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Um vetor tem os ids 11, 12 e 13. O código remove apenas o <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?
  1. Remover o id 12 do DOM recém-renderizado uma segunda vez.
  2. Remover o id 12 do vetor de origem antes de renderizar.
  3. Manter uma NodeList estática que exclua o elemento removido.
  4. Ordenar o vetor de origem antes de construir a próxima visão.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Uma cadeia JSON é [{"id":24,"done":false}]. Após JSON.parse(), como os tipos de id e done se comparam ao data-id="24" de um elemento?
  1. O id analisado é numérico; done é booleano; o id de dataset é texto.
  2. O id analisado é texto; done é texto; o id de dataset é numérico.
  3. O id analisado é numérico; done é texto; o id de dataset é numérico.
  4. O id analisado é texto; done é booleano; o id de dataset é texto.
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

Um artigo contém <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?
  1. label.closest(".card")
  2. label.parentElement.parentElement
  3. label.querySelector(".card")
  4. label.nextElementSibling?.parentElement
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 2 de 10

Uma lista vazia recebe um retrato estático 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?
  1. Retrato estático 0, dinâmica 0.
  2. Retrato estático 2, dinâmica 0.
  3. Retrato estático 2, dinâmica 2.
  4. Retrato estático 0, dinâmica 2.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 3 de 10

Uma prévia exibe um comentário fornecido por um usuário. Uma pessoa desenvolvedora filtra primeiro as tags <script>. Qual atualização mantém o elemento de prévia e insere o comentário como texto literal, sem análise de HTML?
  1. preview.innerHTML = comment
  2. preview.textContent = comment
  3. preview.insertAdjacentHTML("beforeend", comment)
  4. preview.outerHTML = comment
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 4 de 10

Como o código pode associar um rótulo ao campo cujo id é “contact” usando a propriedade DOM do rótulo?
  1. label.for = "contact"
  2. label.id = "contact"
  3. label.htmlFor = "contact"
  4. label.className = "contact"
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 5 de 10

Uma linha começa com 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?
  1. false, false; apenas row permanece.
  2. false, true; row e selected permanecem.
  3. true, false; apenas row permanece.
  4. true, true; row e selected permanecem.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 6 de 10

Uma barra de progresso representa 7 registros concluídos de um total de 20. Qual cadeia de caracteres define corretamente sua largura percentual?
  1. "0.35%"
  2. "35px"
  3. "35%"
  4. "7%"
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 7 de 10

Um painel começa oculto e seu botão informa aria-expanded “false”. Duas vezes, o código salva const open = panel.hidden, define panel.hidden = !open e escreve String(open) em aria-expanded. Quais são os estados finais?
  1. Hidden false; aria-expanded “true”.
  2. Hidden true; aria-expanded “true”.
  3. Hidden false; aria-expanded “false”.
  4. Hidden true; aria-expanded “false”.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 8 de 10

Um item <li id="copy-me"><span>Map</span></li> é copiado com cloneNode(false). O que o clone desconectado contém?
  1. O li e o span, mas sem o id.
  2. O li e seu id, sem span ou texto.
  3. O li, o id, o span e o texto “Map”.
  4. Apenas um nó de texto contendo “Map”.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 9 de 10

Para cada um de três registros, o código clona profundamente um template de um item, preenche seu título e acrescenta o clone a um fragmento de agrupamento. Depois, chama list.replaceChildren(fragment). Quais objetos permanecem preenchidos?
  1. A lista e o fragmento de agrupamento; o template de origem está vazio.
  2. Apenas o template de origem; a lista recebe fragmentos vazios.
  3. A lista e o template de origem; o fragmento de agrupamento está vazio.
  4. Os três; cada um mantém cópias dos mesmos objetos de item.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Questão 10 de 10

Os dados contêm {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?
  1. Converter o id de dataset, atualizar o objeto correspondente e reconstruir todas as linhas a partir dos dados.
  2. Comparar o id de dataset diretamente com ids numéricos e atualizar o objeto encontrado e a linha.
  3. Forçar a classe done da linha existente, deixar o objeto inalterado e reconstruir todas as linhas depois.
  4. Converter o id de dataset, atualizar o objeto correspondente e forçar a classe done da linha existente.
Mostrar respostaOcultar resposta

Salve esta aula para ver esta resposta.

Travou em uma questão sua? Ajuda com Tarefas

Termos-Chave

74 Termos-Chave, cada um com sua definição

A

Alternância de classe com estado forçado
Uma alternância de classe com estado forçado define a presença de uma classe a partir de um segundo argumento booleano, mantendo a classe alinhada a um estado conhecido.
row.classList.toggle("done", task.done) mantém a linha consistente em renderizações repetidas.
Análise sintática
A análise sintática transforma a marcação HTML lida pelo navegador em uma árvore de documento estruturada.
Ao analisar linhas diretamente dentro de uma tabela, o navegador pode inserir um elemento <tbody>.
Atributo
Um atributo é um valor HTML nomeado em um elemento que pode ser lido ou alterado por métodos como getAttribute() e setAttribute().
O atributo href de um link pode conter “/help”, enquanto sua propriedade informa uma URL completa resolvida.
Atributo ARIA
Um atributo ARIA fornece informações sobre o papel, o estado ou o nome de um elemento para tecnologias assistivas como leitores de tela.
Definir aria-label como “Close dialog” fornece um nome acessível para um botão que contém apenas um ícone.
Atributo aria-expanded
O atributo aria-expanded descreve para a tecnologia assistiva se um controle está aberto ou fechado, usando as cadeias de caracteres “true” ou “false”.
Quando um painel de resposta abre, o botão que o controla também deve informar aria-expanded="true".
Atributo booleano
Um atributo booleano representa verdadeiro quando está presente e falso quando está ausente, independentemente do texto escrito como seu valor.
Um botão permanece desabilitado após setAttribute("disabled", "false") porque o atributo existe.
Atributo de dados
Um atributo de dados é um atributo HTML personalizado que começa com data- e armazena informações para scripts sem exibi-las como texto.
Uma linha com data-id="26" pode ser associada ao objeto que forneceu seus campos exibidos.
Atributo defer
O atributo defer adia um script externo clássico até o fim da análise do HTML.
Um script com execução adiada no head pode encontrar um elemento de rodapé escrito perto do fim do body.
Atualização pontual
Uma atualização pontual altera um elemento existente para corresponder aos dados alterados, mantendo o objeto de elemento e seu estado local.
Atualizar a classe done de uma linha pode preservar o foco que seria perdido se todas as linhas fossem reconstruídas.

C

Clone profundo
Um clone profundo copia um nó, seus atributos e toda a sua subárvore de descendentes.
Clonar profundamente um cartão preenchido copia seu texto e seus spans aninhados, além de seu id original.
Coalescência nula
A coalescência nula seleciona uma alternativa com ?? 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
Uma coleção dinâmica atualiza seus membros para refletir o DOM atual, portanto alterações podem mudar seu tamanho e seus índices durante um laço.
Remover uma classe correspondente enquanto se conta em ordem crescente pode fazer um laço ignorar o próximo membro da coleção dinâmica.
Coleção estática
Uma coleção estática mantém os membros que tinha quando foi criada, mesmo que elementos correspondentes sejam posteriormente adicionados à página ou removidos dela.
Um resultado salvo de querySelectorAll() omite um quarto item acrescentado após a pesquisa original.
Coleção HTMLCollection
Uma HTMLCollection é uma coleção indexada dinâmica de elementos que se atualiza conforme mudam as relações entre elementos que a definem.
Remover um filho altera o tamanho e os índices da coleção retornada por list.children.
Coleção NodeList
Uma NodeList é uma coleção DOM indexada com um tamanho; a retornada por querySelectorAll() contém elementos correspondentes.
Converta os parágrafos selecionados com Array.from() antes de usar o método de vetor map().
Comparador
Um comparador informa a uma ordenação como dois valores devem ser ordenados por meio de seu valor de retorno.
O comparador (a, b) => a - b ordena valores numéricos do menor para o maior.
Conteúdo do elemento template
O conteúdo do elemento template é o DocumentFragment separado em template.content, que contém a estrutura filha não exibida do template.
Uma pesquisa no documento não encontra um span de título dentro do template; pesquise em seu conteúdo ou em um clone.
Conversão de tipos
A conversão de tipos altera a representação de um valor, por exemplo, transformando texto numérico de um campo ou atributo de dados em um número.
Number(row.dataset.id) permite que a igualdade estrita compare os algarismos armazenados com o id numérico de um objeto.
Corpo da tabela
O corpo da tabela é a seção <tbody> que agrupa as linhas de dados de uma tabela.
Uma função de renderização acrescenta cada novo <tr> ao corpo selecionado e preenche seus campos em células <td>.

D

Declaração display: none
A declaração display: none oculta um elemento, remove seu espaço no layout e exclui esse conteúdo oculto dos leitores de tela.
Um painel de resposta fechado que usa essa declaração não deixa um bloco vazio no layout da página.
Declaração opacity: 0
A declaração opacity: 0 torna um elemento transparente enquanto preserva seu espaço no layout, sua interação e sua disponibilidade para leitores de tela.
Um botão invisível ainda pode responder a cliques quando apenas sua opacidade foi alterada.
Declaração visibility: hidden
A declaração visibility: hidden oculta um elemento, preserva seu espaço no layout e o oculta dos leitores de tela.
Uma caixa de status invisível pode reservar seu espaço habitual para que o conteúdo ao redor não se mova.

E

Elemento
Um elemento é um nó DOM que representa uma tag HTML, seus atributos e quaisquer nós filhos.
Um elemento <ul> pode conter dois elementos filhos <li>, além de nós de texto com espaços em branco.
Elemento template
Um elemento template contém HTML analisado que não é exibido, fornecendo uma fonte reutilizável para cópias de uma estrutura repetida.
Um template de cartão pode fornecer os mesmos spans de título e detalhe para cada objeto de um vetor de dados.
Estado vazio
Um estado vazio informa aos usuários que não há itens de dados para exibir.
Uma lista de leitura sem livros pode mostrar “Nenhum livro ainda” no lugar de seus itens anteriores.
Estilo computado
Um estilo computado é um valor de estilo resolvido e somente de leitura, disponibilizado pelo navegador após considerar as declarações CSS aplicáveis.
getComputedStyle(title).color pode informar vermelho mesmo quando title.style.color está vazio.
Estilo em linha (inline)
Um estilo em linha é uma declaração CSS no próprio atributo style de um elemento.
Atribuir bar.style.width = "60%" armazena uma largura de progresso calculada diretamente na barra.

F

Ferramentas de desenvolvimento (DevTools)
As ferramentas de desenvolvimento são o conjunto de ferramentas do navegador para examinar o DOM atual, regras CSS, resultados do console e propriedades de elementos.
Selecionar um parágrafo no painel Elementos o disponibiliza como $0 no Console.
Fonte de verdade
Uma fonte de verdade são os dados mantidos como estado de referência, dos quais são derivados os itens e resumos exibidos na página.
Excluir um objeto de um vetor de tarefas a partir do qual uma lista é renderizada impede que a próxima renderização restaure seu item de lista.
Fragmento de documento (DocumentFragment)
Um fragmento de documento é um contêiner fora da página cujos filhos são movidos para o destino quando ele é inserido, deixando o fragmento vazio.
Um fragmento reúne várias novas linhas antes que seus filhos sejam transferidos para o corpo da tabela.
Função de renderização
Uma função de renderização constrói ou atualiza o DOM visível a partir dos dados atuais e pode ser chamada novamente depois que esses dados mudam.
Chamar a função após marcar uma tarefa como concluída atualiza tanto a classe da tarefa quanto uma contagem exibida de tarefas concluídas.

I

Injeção de scripts entre sites (XSS)
A injeção de scripts entre sites é um ataque em que conteúdo não confiável faz código controlado por um invasor ser executado no navegador de um visitante.
Usar textContent para um nome enviado impede que seus caracteres se tornem marcação injetada.
Inserção em lote
A inserção em lote coloca vários nós preparados em um contêiner por meio de uma operação, usando um fragmento ou um vetor de nós expandido.
Construa primeiro os nós de item e depois passe-os juntos para replaceChildren(...items).

M

Método append()
O método append() insere nós ou texto simples após os filhos existentes de um contêiner, aceitando várias entradas em uma chamada.
item.append(title, button) monta dois elementos filhos dentro de um item antes de sua inserção na página.
Método Array.from()
O método Array.from() cria um vetor a partir de uma coleção, permitindo usar métodos de vetor e obter um retrato estático de seus membros.
Array.from(list.children) permite que um laço de remoção visite cada filho original sem deslocamentos de índice.
Método closest()
O método closest() verifica um elemento e seus ancestrais em busca da correspondência mais próxima com um seletor.
Um span dentro de um cartão de produto pode usar closest(".product") para encontrar o cartão que o contém.
Método createElement()
O método createElement() cria um elemento desconectado a partir de um nome de tag, pronto para ser preenchido e inserido no documento posteriormente.
document.createElement("li") cria um item de lista, mas ainda não o adiciona à lista visível.
Método getElementById()
O método getElementById() encontra um elemento por seu id literal, sem pontuação CSS.
document.getElementById("result") procura o id “result”, sem uma cerquilha inicial.
Método insertAdjacentHTML()
O método insertAdjacentHTML() analisa marcação confiável em uma posição nomeada ao lado ou dentro de um elemento, preservando os filhos existentes.
A posição “beforeend” adiciona marcação dentro de um contêiner, após seu último filho atual.
Método insertBefore()
O método insertBefore() insere um nó antes de um filho especificado de um pai ou no fim quando essa referência é null.
list.insertBefore(newItem, list.firstElementChild) coloca o item antes do primeiro elemento filho.
Método prepend()
O método prepend() insere nós ou texto simples antes dos filhos existentes de um contêiner, movendo nós que já existem em outro lugar.
Inserir o último elemento de uma lista no início move esse mesmo objeto para a primeira posição sem copiá-lo.
Método querySelector()
O método querySelector() retorna o primeiro elemento que corresponde a um seletor CSS em sua área de pesquisa, ou null se nenhum corresponder.
Pesquisar dentro de um cartão impede que uma classe .name repetida em outro lugar se torne o resultado.
Método replaceChildren()
O método replaceChildren() substitui os filhos de um contêiner pelos nós ou pelo texto fornecidos ou os remove quando nenhuma entrada é fornecida.
Uma renderização completa usa esse método para remover itens antigos e inserir a exibição recém-construída.
Método replaceWith()
O método replaceWith() substitui o próprio nó selecionado pelos nós ou pelo texto fornecidos em sua posição atual.
Um parágrafo de carregamento pode ser substituído por uma lista concluída enquanto o restante da página permanece no lugar.
Método toFixed()
O método toFixed() retorna um número como uma cadeia de caracteres com uma quantidade especificada de casas decimais, adequada para exibição formatada.
Uma temperatura de 28,5 torna-se a cadeia de caracteres “28.5” com toFixed(1) antes da inserção em uma célula.
Modelo de Objetos do Documento (DOM)
O Modelo de Objetos do Documento é a árvore dinâmica de objetos da página mantida pelo navegador, disponibilizada por meio de uma API que JavaScript pode ler e alterar.
Um script atualiza um título por meio do DOM enquanto a página permanece aberta no navegador.

N

Nó
Um nó é um objeto na árvore DOM, como um elemento, texto, comentário ou o documento.
O elemento de parágrafo e o texto que ele contém ocupam nós separados na árvore da página.
Nó ancestral
Um nó ancestral é um pai ou outro nó mais distante que contém o nó no caminho em direção ao documento.
Uma lista é ancestral do texto dentro de um span aninhado em um de seus itens.
Nó de texto
Um nó de texto contém caracteres no DOM, incluindo palavras visíveis ou espaços em branco entre tags.
Uma lista indentada pode começar com um nó de texto que contém uma quebra de linha antes de seu primeiro item.
Nó desconectado
Um nó desconectado é um nó fora da árvore do documento que ainda pode existir na memória enquanto um script mantém uma referência a ele.
Um item removido pode ser acrescentado novamente por meio da variável que ainda se refere ao seu objeto.
Nó filho
Um nó filho é um nó diretamente dentro de outro, sem um pai intermediário.
O texto dentro de um span aninhado é descendente do item de lista, mas é filho direto do span.
Nó irmão
Um nó irmão é um nó que compartilha o mesmo pai imediato com outro nó na árvore DOM.
Dois itens de lista adjacentes são elementos irmãos mesmo que haja um nó de texto com espaços em branco entre eles.
Nó pai
Um nó pai é o nó imediatamente acima de outro na árvore, contendo-o como filho.
Em <ul><li>Read</li></ul>, a lista é o pai imediato do elemento de item.
Nome individual de classe
Um nome individual de classe é um nome de classe separado dos demais nomes no atributo class por espaços em branco.
Passe “large” e “red” separadamente para classList.add() para que nenhum dos nomes contenha espaço.
Notação camelCase
A notação camelCase une palavras com as iniciais das palavras posteriores em maiúscula, como em backgroundColor.
A propriedade CSS background-color é escrita como style.backgroundColor em JavaScript.

O

Ordenação no próprio vetor (in-place)
A ordenação no próprio vetor reordena o vetor original, portanto suas referências existentes veem a nova ordem.
Copie com [...items] antes de chamar sort() quando a ordem de origem precisar permanecer inalterada.

P

Propriedade
Uma propriedade é um valor ou método nomeado no objeto JavaScript de um elemento, que às vezes disponibiliza dados de atributos processados ou com tipos definidos.
A propriedade disabled retorna um booleano, enquanto a leitura de um atributo retorna uma cadeia de caracteres ou null.
Propriedade checked
A propriedade checked informa o estado atual de seleção de uma caixa de seleção como um booleano, independentemente de seu atributo checked inicial.
Depois que o usuário desmarca uma caixa inicialmente selecionada, sua propriedade checked torna-se falsa.
Propriedade classList
A propriedade classList disponibiliza os nomes individuais de classe de um elemento e métodos para adicioná-los, removê-los, testá-los, alterná-los ou substituí-los individualmente.
Adicionar “selected” por meio de classList mantém a classe “card” existente e seu estilo básico.
Propriedade className
A propriedade className é a cadeia completa de classes; atribuir-lhe um valor substitui todas as classes.
Atribuir “active” ao className de um cartão remove sua antiga classe “card”, a menos que ela seja incluída novamente.
Propriedade dataset
A propriedade dataset disponibiliza os atributos de dados de um elemento como entradas com valores em cadeias de caracteres e nomes convertidos para a notação camelCase.
Escrever row.dataset.recordId = "26" cria ou altera o atributo data-record-id.
Propriedade hidden
A propriedade hidden controla o estado comum de ocultação, mantendo o elemento no DOM enquanto o estilo padrão remove seu espaço no layout.
Defina panel.hidden = false para revelar um painel que foi ocultado sem reconstruir seu conteúdo.
Propriedade innerHTML
A propriedade innerHTML lê a marcação interna e analisa a marcação atribuída para criar novos nós filhos, substituindo os filhos existentes.
Atribuir a cadeia confiável "<strong>Ready</strong>" cria um novo elemento strong dentro do contêiner.
Propriedade innerText
A propriedade innerText lê o texto de acordo com o layout renderizado, ignorando descendentes ocultos de um elemento exibido.
O innerText de um rótulo visível omite uma nota aninhada com o estilo display: none.
Propriedade outerHTML
A propriedade outerHTML inclui a própria marcação de um elemento; atribuir-lhe um valor substitui o próprio elemento por nós recém-analisados.
Após a substituição, uma variável que contém o parágrafo original ainda se refere ao objeto desconectado.
Propriedade personalizada CSS
Uma propriedade personalizada CSS é um valor CSS nomeado que começa com dois hífens e ao qual regras podem fazer referência por meio da função var().
Defina "--accent" por meio de style.setProperty() para alterar regras que fazem referência ao valor de destaque.
Propriedade textContent
A propriedade textContent lê o texto dos descendentes e, quando recebe um valor, substitui os nós filhos por texto simples sem analisar HTML.
Atribuir “Ready” exibe esses caracteres e não cria um elemento de ênfase.
Propriedade value
A propriedade value contém o valor atual de um controle de formulário como uma cadeia de caracteres, que pode diferir de seu atributo HTML inicial.
Ler um campo de quantidade após a edição retorna o texto digitado atual, não seu valor original.

R

Renderização
A renderização é o processo de construir ou atualizar conteúdo DOM a partir de dados para que a página visível represente os valores atuais.
Um vetor de livros torna-se uma lista pela construção de um item com título e quantidade de páginas por objeto.

S

Seletor CSS
Um seletor CSS é um padrão que corresponde a elementos por características como tag, classe, id ou aninhamento.
O seletor "#profile .name" encontra descendentes com a classe name do elemento de perfil.
Sintaxe de espalhamento (spread)
A sintaxe de espalhamento expande um iterável em valores separados, permitindo que um vetor de nós seja passado como argumentos individuais de um método.
list.append(...items) insere cada nó construído em vez da representação do vetor como cadeia de caracteres.

U

Unidade CSS
Uma unidade CSS dá significado a um comprimento ou outro valor de estilo, como pixels para uma largura absoluta ou porcentagem para uma largura relativa.
Uma largura diferente de zero precisa de texto como “180px”; um número sem unidade é ignorado no modo padrão.

V

Valor nulo (null)
null é o valor explícito de resultado ausente retornado por pesquisas de um único elemento e por propriedades da árvore quando não existe um objeto correspondente.
Verifique uma referência ausente a um banner antes de definir seu texto, pois ler de null lança um erro.
Visão derivada
Uma visão derivada é um vetor filtrado ou reordenado usado para exibição enquanto os dados originais permanecem disponíveis para outras visões.
Mostre tarefas não concluídas com tasks.filter(task => !task.done) sem descartar as concluídas.

Sobre esta aula

Por StudeliRelatar um erro

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.

Começar