Aula 3: JS - Manipulação Avançada da DOM

Removendo JS Inline e Event Listeners

Na aula passada, vimos como adicionar eventos usando onclick="..." direto no HTML. Agora, vamos ver algumas maneiras de melhorar o design das nossas páginas. Primeiro, assim como tentamos evitar estilização inline com CSS, queremos evitar JavaScript inline sempre que possível.

Podemos fazer isso adicionando uma linha de script que muda o atributo onclick de um botão na página, removendo-o de dentro da tag <button>:

document.querySelector('button').onclick = contar;

Não estamos chamando a função com parênteses (contar()), mas apenas nomeando-a (contar). Isso especifica que só queremos chamar a função quando o botão for clicado.

Porém, esta mudança sozinha pode gerar um erro no console do navegador, pois o código JavaScript pode rodar antes do botão ter sido renderizado na tela:

Para contornar isso, usamos a função addEventListener. Ela espera a página carregar (DOMContentLoaded) antes de executar o código:

document.addEventListener('DOMContentLoaded', function() {
    // Agora é seguro buscar o botão
    document.querySelector('button').onclick = contar;
});

Arquivos Separados (.js)

Outra maneira de melhorar o código é movendo nosso JavaScript para um arquivo separado (ex: contador.js). É muito similar ao CSS:

<script src="/static/contador.js"></script>

Isso traz vantagens como: apelo visual (código mais limpo), compartilhamento entre várias páginas HTML, facilidade de colaboração em equipe e importação de bibliotecas externas (como o JS do Bootstrap).

Estilização, datasets e o Console

Com JavaScript, também podemos mudar a estilização de uma página! Usamos atributos data-ALGO no HTML para guardar informações, e lemos isso via dataset no JS.

<button data-cor="red">Vermelho</button>
// Pegando todos os botões e mudando a cor do texto com base no data-cor
document.querySelectorAll('button').forEach(function(botao) {
    botao.onclick = function() {
        document.querySelector("#ola").style.color = botao.dataset.cor;
    }
});

Console do JavaScript

O console é útil para depuração. Usamos a função console.log() para imprimir algo lá:

console.log(document.querySelectorAll('button'));

Arrow Functions e Eventos

O JavaScript moderno nos permite encurtar funções usando a sintaxe Arrow Function (=>):

document.addEventListener('DOMContentLoaded', () => {
    document.querySelectorAll('button').forEach(botao => {
        botao.onclick = () => {
            document.querySelector("#ola").style.color = botao.dataset.cor;
        }
    });
});

Além do onclick, podemos ouvir inúmeros eventos como onchange (útil para menus dropdown <select>), onmouseover, onkeyup, entre outros.

Lista de Tarefas (Aplicações Reais)

Vamos juntar tudo criando uma lista de tarefas. Precisaremos ler um input, habilitar/desabilitar um botão (disabled) e criar novos elementos HTML (createElement e append).

document.addEventListener('DOMContentLoaded', () => {
    const submit = document.querySelector('#submit');
    const novaTarefa = document.querySelector('#tarefa');
    submit.disabled = true;

    // Ouve quando soltamos uma tecla no input
    novaTarefa.onkeyup = () => {
        if (novaTarefa.value.length > 0) {
            submit.disabled = false;
        } else {
            submit.disabled = true;
        }
    }

    // Ouve o envio do formulário
    document.querySelector('form').onsubmit = () => {
        const tarefa = novaTarefa.value;
        const li = document.createElement('li');
        li.innerHTML = tarefa;

        document.querySelector('#tarefas').append(li);
        novaTarefa.value = ''; // Limpa o input
        submit.disabled = true;

        return false; // Previne a página de recarregar
    }
});

Intervalos

Podemos configurar funções para rodar repetidamente usando setInterval, que recebe a função a ser executada e o tempo (em milissegundos).

function contar() {
    contador++;
    document.querySelector('h1').innerHTML = contador;
}

document.addEventListener('DOMContentLoaded', () => {
    setInterval(contar, 1000); // Roda a cada 1 segundo
});

Local Storage (Salvando Dados)

Toda vez que recarregamos a página, nossos contadores e tarefas são perdidos. Para resolver isso, usamos o Local Storage do navegador. Funciona como um dicionário chave-valor do Python:

if (!localStorage.getItem('contador')) {
    localStorage.setItem('contador', 0);
}
            
function contar() {
    let contador = localStorage.getItem('contador');
    contador++;
    document.querySelector('h1').innerHTML = contador;
    localStorage.setItem('contador', contador);
}

document.addEventListener('DOMContentLoaded', () => {
    document.querySelector('h1').innerHTML = localStorage.getItem('contador');
    document.querySelector('button').onclick = contar;
});

Isso é tudo para nossa jornada nos fundamentos do JavaScript! Agora nossos sites ganharam memória e vida própria.

Exercícios