Mini projeto — Lista de tarefas interativa
A prova de que a lista funciona é tirá-la do zero e devolvê-la ao zero. Você inclui buy tea, marca como feita e remove. Aberta, a linha mostra buy tea. Feita, mostra done: buy tea.
A página anterior parou nos nomes
Lá só havia o nome das habilidades, nenhuma lista na tela. Esta página é a lista. Você usa um array, um formulário, textContent e um clique. Incluir não pode recarregar a página.
Objeto, não texto solto
tasks é um array de objetos. Cada objeto tem text e done. O item novo começa com done em false. addTask passa as palavras por trim. Se não sobra nada, não há push e o item não fica guardado.
const tasks = [];
function addTask(text) {
const clean = text.trim();
if (!clean) {
return;
}
tasks.push({ text: clean, done: false });
}
addTask("buy tea");
console.log(tasks[0].text);
console.log(tasks[0].done);
Os dois registros saem nesta ordem: buy tea, depois false. addTask(" ") perde as letras no trim, não guarda nada e o comprimento continua 0.
Recarregar deita o array fora
Enviar um formulário recarrega o documento. O array só existe na memória, por isso a recarga o deixa cair e a lista parece vazia. event.preventDefault() corta essa recarga. A seguir você põe o texto, limpa o campo e desenha de novo.
const form = document.querySelector("#add-form");
const input = document.querySelector("#task-text");
form.addEventListener("submit", (event) => {
event.preventDefault();
addTask(input.value);
input.value = "";
render();
});
O documento fica. O campo fica vazio. render corre. Um campo só de espaços não acrescenta linha.
Dois botões que não enviam
render esvazia #tasks e monta um li por item. O aberto mostra text. O feito mostra done: e em seguida o texto. Cada linha tem dois botões, ambos com type="button", para não enviarem o formulário. Done inverte o booleano. Remover usa splice. Os dois desenham outra vez, porque os índices velhos apontariam para o item errado.
function toggleTask(index) {
tasks[index].done = !tasks[index].done;
}
function removeTask(index) {
tasks.splice(index, 1);
}
function render() {
const list = document.querySelector("#tasks");
list.textContent = "";
tasks.forEach((task, index) => {
const item = document.createElement("li");
item.textContent = task.done ? "done: " + task.text : task.text;
const doneButton = document.createElement("button");
doneButton.type = "button";
doneButton.textContent = "Done";
doneButton.addEventListener("click", () => {
toggleTask(index);
render();
});
const removeButton = document.createElement("button");
removeButton.type = "button";
removeButton.textContent = "Remove";
removeButton.addEventListener("click", () => {
removeTask(index);
render();
});
item.append(doneButton, removeButton);
list.append(item);
});
}
A ordem é addTask("buy tea"), toggleTask(0), render. A linha fica done: buy tea. Outro toque e volta a buy tea. removeTask(0) deixa o comprimento em 0 e o desenho seguinte não tem linhas. As palavras do campo entram com textContent. Não as cole na página como HTML.
O índice é desta passagem
forEach guarda o índice dessa passagem. Depois do splice, os números velhos apontam para a tarefa errada. Desenhar de novo joga fora os botões antigos e faz outros com os índices de agora. Sem esse segundo desenho, Remove apaga a linha errada.
Três ofícios
O formulário inclui. A lista desenha. Done e Remove só mudam tasks e depois desenham de novo.
<!DOCTYPE html>
<html>
<body>
<form id="add-form">
<input id="task-text" type="text">
<button type="submit">Add</button>
</form>
<ul id="tasks"></ul>
<script>
const tasks = [];
function addTask(text) {
const clean = text.trim();
if (!clean) return;
tasks.push({ text: clean, done: false });
}
function toggleTask(index) {
tasks[index].done = !tasks[index].done;
}
function removeTask(index) {
tasks.splice(index, 1);
}
function render() {
const list = document.querySelector("#tasks");
list.textContent = "";
tasks.forEach((task, index) => {
const item = document.createElement("li");
item.textContent = task.done ? "done: " + task.text : task.text;
const doneButton = document.createElement("button");
doneButton.type = "button";
doneButton.textContent = "Done";
doneButton.addEventListener("click", () => {
toggleTask(index);
render();
});
const removeButton = document.createElement("button");
removeButton.type = "button";
removeButton.textContent = "Remove";
removeButton.addEventListener("click", () => {
removeTask(index);
render();
});
item.append(doneButton, removeButton);
list.append(item);
});
}
document.querySelector("#add-form").addEventListener("submit", (event) => {
event.preventDefault();
addTask(document.querySelector("#task-text").value);
document.querySelector("#task-text").value = "";
render();
});
</script>
</body>
</html>
Digite buy tea e clique em Add. A linha fica buy tea e o campo fica vazio. Clique em Done e a linha fica done: buy tea. Clique em Remove e a lista fica vazia. Add num campo em branco não inclui nada.
Cinco passos na mesa
- Chame addTask("buy tea"). O primeiro text é buy tea e done é false.
- Envie o formulário. A página não recarrega e a linha aparece.
- Clique em Done. A linha mostra done: buy tea.
- Clique em Remove. tasks.length fica 0.
- Envie só espaços. A lista não cresce.
Erros que acontecem de verdade
- saltar preventDefault e deixar o array morrer no envio
- fazer push de uma cadeia vazia
- pôr type="submit" em Done ou Remove
- apagar a linha na tela e esquecer splice, de modo que o desenho seguinte a traz de volta
- saltar render depois de splice
- escrever o campo na página como HTML
O que fica
- Uma tarefa é { text, done } e done começa em false
- addTask("buy tea") guarda buy tea; um campo em branco não guarda nada
- preventDefault mantém a página e render desenha as linhas
- Done mostra done: buy tea e Remove deixa o comprimento em 0
- Desenhe de novo depois de cada mudança
🧠 Teste Seu Conhecimento
Teste Seu Conhecimento
Desafie-se com este questionário interativo e veja o quão bem você entende o tópico
📝 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