Carregando...

Delegação de eventos

Na bilheteira há uma faixa. O pai é #strip. Já tem dois botões: #red, com o texto red, e #blue, com o texto blue. Por baixo, #note diz blank.
Não precisas de um ouvinte em cada botão. Uma chamada a addEventListener na faixa chega. O clique de um botão lá dentro sobe até à faixa. event.target é o botão. event.currentTarget é a faixa, o elemento onde este ouvinte está.
O botão #gold ainda não está na página. Nasce depois de o ouvinte ficar guardado, é acrescentado à faixa e é clicado. A mesma função corre. A nota passa a gold. O script clica red, depois blue, depois gold. addEventListener correu uma vez, por isso hands vale 1. A linha sob a faixa é red / blue / gold / 1. Estes botões são type="button". Aqui não se chama preventDefault nem stopPropagation. Isso era a página da placa, e lá não se acrescentava um filho depois do ouvinte.

Um ouvinte para cada bilhete

A página da placa dava o nome event ao parâmetro e lia type, target e currentTarget numa ligação dentro da parede. A linha era click / seal / plaque / true / quiet. O cabide guardava wool e silk sem parâmetro. A linha era wool silk / 2 / peg. Aqui o parâmetro event fica, mas target tem outro ofício: dizer qual filho recebeu o clique, mesmo um filho que ainda não existia.
getElementById só te dá a faixa, o botão vermelho, o botão azul e a nota. Gold nasce de createElement. Um ouvinte em red e outro em blue falham gold, a menos que voltes a prender depois de appendChild. Um ouvinte na faixa não precisa dessa segunda prisão. Lê currentTarget dentro da função. Quando a função volta, essa propriedade é null.

O que a faixa regista

A nota começa em blank. Os rótulos continuam red e blue; gold chega depois. Lê as linhas por ordem. Cada excerto parte da faixa com dois botões, excepto a linha da página, que é a demo em baixo. Essa demo chama addEventListener uma vez.

📊 O que a faixa regista

Momento O que lês Texto da nota Confusão fácil
ouvinte na faixa, clique em red event.target.id red ler currentTarget, que é strip
o mesmo clique, ler currentTarget event.currentTarget.id strip ler o id do bilhete
o mesmo ouvinte, clique em blue event.target.id blue dar a blue um ouvinte próprio
gold criado depois do ouvinte e clicado event.target.id gold achar que o botão novo fica mudo
clique na faixa, com o guarda a nota skip escrever o id strip
script da página a linha red / blue / gold / 1 a linha da placa, ou um 3 no fim

Um clique num botão é um só evento. target continua a ser esse botão para cada ouvinte no caminho. Aqui há um ouvinte, na faixa, por isso enquanto a função corre currentTarget é a faixa. O clique chega porque ninguém chama stopPropagation. A página da placa cortava essa viagem. Esta não corta.
preventDefault serve para uma acção por omissão do navegador, como uma ligação que sai da página. Estes controlos são botões, não ligações. Não chamar preventDefault é a página inteira, não uma linha em falta.
Se event.target e event.currentTarget forem o mesmo nó, o clique caiu na faixa, não num botão. A função escreve skip e não trata o papel como bilhete. seen.join(" / ") só junta ids que já entraram em seen. hands vem a seguir. O último token é quantas vezes se chamou addEventListener, não quantos bilhetes foram clicados.

O bilhete sob o clique

O ouvinte está na faixa. A função dá ao parâmetro o nome event e escreve event.target.id na nota. Depois a página clica red. Não chama addEventListener em red.

Ler o bilhete

javascript
let strip = document.getElementById("strip");
let note = document.getElementById("note");
function take(event) {
note.textContent = event.target.id;
}
strip.addEventListener("click", take);
document.getElementById("red").click();
console.log(note.textContent);

A saída é red. O elemento do ouvinte é a faixa. target não fala do pai. Fala do botão que ficou sob o clique.

De quem é o ouvinte

Faixa nova, o mesmo ouvinte, o mesmo clique em red. A nota escreve os dois ids, target primeiro e currentTarget depois.

Ler os dois ids

javascript
let strip = document.getElementById("strip");
let note = document.getElementById("note");
function take(event) {
note.textContent = event.target.id + " " + event.currentTarget.id;
}
strip.addEventListener("click", take);
document.getElementById("red").click();
console.log(note.textContent);

A saída é red strip. A primeira palavra é o bilhete. A segunda é o elemento dono deste ouvinte. Se o ouvinte estivesse no próprio red e clicasses red, saía red red. Esta leitura usa a faixa, por isso os ids diferem.

O bilhete que já estava ao lado

Outra faixa nova. Um ouvinte, ainda só na faixa. Desta vez o clique é blue. Blue estava na marcação desde o início. Não tem ouvinte próprio.

Ouvir o outro bilhete

javascript
let strip = document.getElementById("strip");
let note = document.getElementById("note");
function take(event) {
note.textContent = event.target.id;
}
strip.addEventListener("click", take);
document.getElementById("blue").click();
console.log(note.textContent);

A saída é blue. Um addEventListener cobriu os dois botões que já estavam dentro da faixa. Blue não substituiu red. Red não precisou de uma segunda chamada.

Um bilhete impresso mais tarde

Primeiro guarda-se o ouvinte. Depois a página constrói um botão, põe o id em gold, type em button, o texto em gold e acrescenta-o à faixa. Só então clica gold.

Ouvir um bilhete tardio

javascript
let strip = document.getElementById("strip");
let note = document.getElementById("note");
function take(event) {
note.textContent = event.target.id;
}
strip.addEventListener("click", take);
let gold = document.createElement("button");
gold.id = "gold";
gold.type = "button";
gold.textContent = "gold";
strip.appendChild(gold);
gold.click();
console.log(note.textContent);

A saída é gold. Gold não existia quando addEventListener correu. O clique sobe de gold até à faixa, e target é gold. Não prendes um ouvinte a gold.

Um clique no papel

A faixa também é um nó que se pode clicar. Se o target do clique for a faixa, não há id de bilhete para guardar. A função compara target com currentTarget. Se forem iguais, a nota passa a skip.

Ignorar o clique na faixa

javascript
let strip = document.getElementById("strip");
let note = document.getElementById("note");
function take(event) {
if (event.target === event.currentTarget) {
note.textContent = "skip";
return;
}
note.textContent = event.target.id;
}
strip.addEventListener("click", take);
strip.click();
console.log(note.textContent);

A saída é skip. Tanto target como currentTarget são a faixa, por isso o guarda recusa o papel. Um clique em red continua a escrever red, porque as duas referências diferem. Sem o guarda, strip.click() escreveria o id strip na nota.

A linha sob a faixa

O script fica no fim de body, depois de a faixa e os parágrafos existirem. Guarda-se um ouvinte e hands passa a 1. Clica-se red e depois blue. Cada id de bilhete entra em seen. Gold é criado, acrescentado e clicado, por isso gold também entra em seen. A linha é escrita depois desse terceiro clique. A página não clica a faixa, por isso skip não está na linha.

Demo da página — faixa de bilhetes

html
<!DOCTYPE html>
<html>
<head>
<title>event-delegation — page</title>
</head>
<body>
<div id="strip">
<button id="red" type="button">red</button>
<button id="blue" type="button">blue</button>
</div>
<p id="note">blank</p>
<p id="line">…</p>
<script>
let strip = document.getElementById("strip");
let note = document.getElementById("note");
let seen = [];
let hands = 0;
function take(event) {
if (event.target === event.currentTarget) {
note.textContent = "skip";
return;
}
note.textContent = event.target.id;
seen.push(event.target.id);
}
strip.addEventListener("click", take);
hands = hands + 1;
document.getElementById("red").click();
document.getElementById("blue").click();
let gold = document.createElement("button");
gold.id = "gold";
gold.type = "button";
gold.textContent = "gold";
strip.appendChild(gold);
gold.click();
document.getElementById("line").textContent =
seen.join(" / ") + " / " + hands;
</script>
</body>
</html>

A linha lê-se red / blue / gold / 1. Os três ids são os bilhetes clicados, por essa ordem. O último token é hands. addEventListener correu uma vez, por isso o token é 1, não 3. A nota acaba em gold, porque gold foi o último clique. A palavra blank desapareceu. A palavra skip não aparece. A linha da placa e a do cabide são outras páginas.
Um botão que só tem texto deixa event.target no botão, por isso id é red, blue ou gold. Um span dentro do botão pode receber o clique. O span não tem id. Esta página não faz isso.

Na bilheteira

  1. Põe um ouvinte na faixa e clica red. A nota é red. Red não tem ouvinte próprio.
  2. Com esse mesmo ouvinte, clica blue. A nota é blue.
  3. Cria gold, acrescenta-o e clica-o. A nota é gold. O ouvinte já estava na faixa.
  4. Clica a faixa. Com o guarda, a nota é skip. Depois lê a linha: red / blue / gold / 1.

O que falha na bilheteira

Os rótulos continuam a dizer red, blue e gold. A nota não é a palavra bilhete.

  • Um ouvinte em red e outro em blue, e depois a surpresa de gold ficar mudo
  • Ler event.currentTarget quando querias o bilhete
  • Ler event.target quando querias a faixa
  • Esquecer o guarda, de modo que strip.click() escreve strip
  • Um span dentro do botão, e então target é o span e o id fica vazio
  • Chamar outra vez addEventListener em gold e contar hands como 2
  • Chamar preventDefault ou stopPropagation; isso era a placa
  • Esperar que o argumento da função seja o elemento botão
  • Ler a linha como click / seal / plaque / true / quiet, ou como wool silk / 2 / peg
  • Ler o último token como 3 porque três bilhetes foram clicados

O que fica

  • Um addEventListener na faixa ouve cada botão lá dentro
  • No clique de red, event.target.id é red e event.currentTarget.id é strip
  • O mesmo ouvinte escreve blue quando blue é clicado
  • Gold, criado depois do ouvinte, escreve na mesma gold
  • Um clique na faixa, com o guarda, escreve skip
  • A linha da página é red / blue / gold / 1

🧠 Teste Seu Conhecimento

Pronto para Começar

Teste Seu Conhecimento

Desafie-se com este questionário interativo e veja o quão bem você entende o tópico

❓
8
Perguntas
🎯
70%
Para Passar
♾️
∞
Tempo
🔄
∞
Tentativas

📝 Instruções

  • Leia cada pergunta cuidadosamente
  • Selecione a melhor resposta para cada pergunta
  • Você pode refazer o quiz quantas vezes quiser
  • Seu progresso será mostrado no topo