Programação Orientada a Eventos...
Eventos são coisas que acontecem quando o usuário interage com um site. Achou estranho o termo "coisas"? Pois é assim mesmo que a W3C define os eventos . 😛
Eles podem ser de vários tipos:
Mouse: clique, scroll, clique duplo
Teclado: pressionar uma tecla, soltar uma tecla
Página: terminar de pintar os elementos HTML, finalizar o carregamento completo da página
Entre outros
Nesse post você vai ver muita coisa sobre eventos:
Adicionar um evento
Adicionar mais de um evento
Substituir
Remover
Como ter acesso às informações do evento
Assim que você cria um, é preciso informar uma função callback. Ela irá executar assim que o evento disparar.
Até o momento aprendi 3 formas de adicionar eventos em Javascript.
Adicionar evento Javascript pelo atributo do elemento HTML
Uma dica: evite essa forma.
Eu evito ela quando trabalho com Javascript puro, sem framework:
<button class="button" onclick="myFunction()">
OK!
</button>
function myFunction() {
console.log('Clicou no botão "OK!"');
}
O motivo de não gostar muito desse método é que a declaração da função fica no arquivo Javascript, enquanto a execução fica no HTML.
Prefiro deixar tudo no arquivo Javascript, e essa será a forma que você vai ver agora.
Adicionar evento Javascript com o método addEventListener
Essa forma é a "oficial".
Acredito que a maioria das pessoas usem ela:
<button class="button">
OK!
</button>
const button = document.querySelector('.button');
button.addEventListener('click', function() {
console.log('Clicou no botão "OK!"');
});
Costumo usar essa forma para adicionar mais de um eventos no mesmo elemento. Assim document.addEventListener()
e assim window.addEventListener()
.
A terceira forma que vou ensinar é bem parecida com essa porém um pouco mais simples. Veja abaixo.
Adicionar evento Javascript com a propriedade on do elemento HTML
Essa forma é bastante parecida com a anterior.
Se eu quiser adicionar um evento de clique em um botão, uso a propriedade onclick
:
<button class="button">
OK!
</button>
const button = document.querySelector('.button');
button.onclick = function(event) {
console.log('Clicou no botão "OK!"');
});
A diferença é onde você informa a função callback. Se usar o atributo, ela é o valor dele; caso use o addEventListener
, ela será um argumento da função.
Prefiro usar esse método quando vou aplicar um evento em um elemento que recebe um evento só.
Caso precise fazer isso com outro tipo de evento, basta usar esse atributo com on
na frente:
onmouseenter
onmouseleave
onmouseover
.
Essas são as formas mais comuns de adicionar um evento em Javascript.
Mas se tem tantas formas, qual é a diferença entre elas? Talvez você já tenha se perguntado... até hoje.
Diferença entre o método addEventListener e o atributo on
As principais diferença entre elas são duas:
A forma como você remove os eventos
Como acontece a substituição ou adição de novos eventos
Remoção de evento
Remover um evento que você adicionou com o addEventListener
é bem fácil. Use praticamente o mesmo código, porém troque addEventListener
por removeEventListener
:
const button = document.querySelector('.button');
function callbackFunction() {
console.log('Clicou no botão "OK!"');
}
// Adicionar evento
button.addEventListener('click', callbackFunction);
// Remover evento
button.removeEventListener('click', callbackFunction);
Perceba que no código acima eu declarei a função callback antes de adicionar os eventos. Isso porque no removeEventListener
eu preciso informar exatamente qual função quero remover.
Caso eu declarasse a função dentro dos parênteses do addEventListener()
, ela só existiria ali dentro. E assim, seria impossível referenciar ela de fora para remover.
Então se você adicionar um evento que talvez precise ser removido no futuro, use essa estratégia.
Se usar o element.onclick = function() {}
, basta fazer uma nova atribuição, porém agora com o valor null
:
const button = document.querySelector('.button');
// Adicionar evento
button.onclick = function(event) {
console.log('Clicou no botão "OK!"');
});
// Remover evento
button.onclick = null;
Veja agora a outra diferença desses dois modos de adicionar eventos em Javascript.
Substituição ou adição de evento
O método addEventListener
permite que o mesmo elemento possa receber múltiplos eventos.
Está no próprio nome: ele adiciona (add) um escutador (listener) de eventos (event). Isso vale também para eventos do mesmo tipo. Assim, um botão pode ter mais de um evento de clique.
Por outro lado, se você usar a propriedade onclick
, o segundo evento irá sobrescrever o primeiro.
button.onclick = function() {
alert('primeiro clique');
}
button.onclick = function() { // remove o evento acima
alert('segundo clique');
}
Se for a primeira vez que você vê as diferenças entre o addEventListener
e o atributo on...
, pode parecer confuso. Para evitar maiores problemas, use sempre o addEventListener
.
Legal, você já sabe como disparar eventos em Javascript. Mas o que fazer com eles? Pense que a cada disparo, você recebe diversas informações desse evento. Veja agora as principais.
As informações do evento
É aqui que a magia acontece.
Como você viu ao longo desse post, todo ouvinte de evento recebe uma função, e ela executa assim que o evento dispara.
Essa função pode receber como parâmetro um objeto com as informações do evento. Chame-o como quiser:
event
evento
infosDoEvento
Até de
batata
, só peço que não chame dee
(por favor)
elemento.addEventListener('tipoDeEvento', function(batata) {
console.log(batata);
});
Para facilitar a explicação, vou chamar sempre de event
.
Esse objeto possui as informações do evento que acabou de disparar. E claro, as informações dependem do tipo de evento.
Veja algumas propriedades mais comuns:
Elemento HTML alvo do evento
Arrisco dizer que esse é o mais usado.
Use o event.target
quando você quer descobrir qual é o elemento que disparou o evento:
<button class="button">OK!</button>
const button = document.querySelector('.button');
button.addEventListener('click', function(event) {
console.log(event.target); // <button class="button">OK!</button>
});
Essa propriedade está disponível não apenas para eventos de clique, mas também outros eventos comuns de mouse. Quando o ponteiro do mouse:
Passa sobre um elemento:
mouseover
Sai de cima de um elemento:
mouseleave
Se move sobre um elemento:
mousemove
. Dispara a cada pixel que o ponteiro se desloca
Porém, existe uma pegadinha no event.target
. Veja esse outro exemplo com um span
dentro do button
:
<button class="button">
<span>OK!</span>
</button>
const button = document.querySelector('.button');
button.addEventListener('click', function(event) {
console.log(event.target); // ???
});
Nessa situação, event.target
pode apontar tanto para o button
, quanto para o span
. Tudo depende de qual região do botão você clicou.
Se foi em cima do texto "OK!", será o span
. Se o clique foi mais para a borda, então será o button
.
E como ter certeza de quem é o alvo do evento? A solução disso está no próximo capítulo...
Elemento HTML ligado ao event listener
É quase igual ao anterior.
Porém, em vez de receber o elemento que o usuário clicou, você recebe aquele que teve o evento atrelado a ele.
Para isso, use event.currentTarget
:
<button class="button">
<span>OK!</span>
</button>
const button = document.querySelector('.button');
button.addEventListener('click', function(event) {
console.log(event.currentTarget); // Agora com certeza será sempre o button
});
Há um tempo, eu escrevi um post sobre a diferença desses dois targets.
Assim como a propriedade anterior (event.target
), essa daqui também não é exclusiva do evento de clique.
Tecla do teclado que o usuário pressionou
A primeira vez que fiz isso, me senti meio hacker.
document.addEventListener('keydown', function(event) {
console.log(event.altKey); // true ou false
console.log(event.ctrlKey); // true ou false
console.log(event.shiftKey); // true ou false
console.log(event.key); // O nome da tecla que o usuário pressionou
});
Quando você usa eventos de teclado, como o onkeydown
e onkeyup
, as informações do evento são as mesmas. Entre elas, as mais interessantes são:
Descobrir qual foi a tecla que o usuário pressionou (
event.key
)Descobrir se usuário segurou
ctrl
,alt
e/oushift
no momento dokeydown
oukeyup
Valor de um campo de input
Isso é super útil para quando você precisa trabalhar com um valor em tempo real:
Existem três eventos para pegar essa informação, e cada um tem suas características:
onchange
: ocorre quando o usuário muda o valor da caixa deselect
oninput
: ocorre quando o usuário digita uum caractere noinput
onblur
: ocorre quando o foco muda de um elemento para o outro. Funciona tanto cominput
quanto com qualquer element focalizável
Para entender melhor como o focus funciona, eu escrevi esse post sobre o focus em HTML, CSS e Javascript.
Mesmo assim, o onchange
também funciona com o elemento input
, e seu comportamento é igual ao do onblur
. Além disso, o oninput
também funciona com o elemento select
.
E para finalizar essa explicação, assim que o evento dispara, basta pegar o valor do alvo do evento:
const input = document.querySelector('.input');
input.addEventListener('change', function(event) {
console.log(event.target.value);
});
input.addEventListener('input', function(event) {
console.log(event.target.value);
});
input.addEventListener('blur', function(event) {
console.log(event.target.value);
});
Posição da barra de rolagem da página
Essa é outra informação muito importante.
Se sua funcionalidade depende do scroll da página, use os eventos onscroll
e onwheel
. A diferença entre eles é muito pequena:
onscroll
: o evento dispara quando a barra de rolagem da página se move. Esse evento depende da páginaonwheel
: o evento dispara quando o usuário usa o scroll do mouse, touchpad ou outro dispositivo. Esse evento depende do hardware do usuário
A melhor forma de entender a diferença é:
Adicione os dois eventos na mesma página
Role a página de rolagem até o final ou até o topo
Durante esse trajeto, você irá perceber que os dois eventos disparam
Quando atingir o início ou fim da página e continuar tentando avançar, apenas o
onwheel
irá dispararO
onscroll
dispara apenas enquanto a página não chegou no seu limite
Você pode adicionar esse evento na página inteira (document
), ou em um elemento com scroll interno:
document.addEventListener('scroll', function(event) {
console.log('scroll', event);
});
document.addEventListener('wheel', function(event) {
console.log('wheel', event);
});
Assim que o evento disparar, você pode descobrir qual é a posição da barra de rolagem na tela. Basta pegar o valor de:
window.pageXOffset
: a posição da barra de rolagem horizontalwindow.pageYOffset
: a posição da barra de rolagem vertical
Perceba que esses valores estão dentro do objeto global window
e não em event
. Logo, você também tem acesso a eles fora dos eventos de onscroll
e onwheel
.
Uma ótima forma de usar os eventos de scroll, é criar o efeito de lazyload. Nele, o navegador baixa as imagens apenas quando se aproximam da área de visualização da tela, e não no carregamento da página.
Você pode ver a aplicação disso nesse post onde mostrei como criar o efeito de lazyload.
Callback
Você pode adicionar eventos em Javascript de três formas:
Pelo atributo HTML
Pelo método
addEventListener
do JavascriptOu pela propriedade
on...
do elemento HTML
As duas últimas opções são bem parecidas, mas têm diferenças quanto a remover ou substituir o evento.
Use o argumento da função callback para pegar informações do evento que disparou. Essas informações dependem do tipo de evento, mas as mais comuns são:
O elemento HTML que disparou o evento
O elemento HTML ligado ao event listener
A tecla que o usuário pressionou
O valor do campo de input
A posição da barra de rolagem
Esse tipo de conteúdo eu gostaria de ter lido quando comecei a estudar Javascript. Mas saiba que fui descobrir como usar o event.target
apenas na minha primeira experiência como dev. Foi uma descoberta que explodiu minha cabeça.
Então espero que esse post tenha esclarecido para você algumas coisas sobre eventos em Javascript.