# Manipulação de Eventos
# Escutando Eventos
Podemos usar a diretiva v-on, que normalmente abreviamos para o símbolo @, para escutar eventos do DOM e rodar algum JavaScript quando tal evento for disparado. A maneira de usar seria v-on:click="nomeDoMétodo" ou com o atalho, @click="nomeDoMétodo"
Por exemplo:
<div id="basic-event"> <button @click="counter += 1">Adicionar 1</button> <p>O botão acima foi clicado {{counter}} vezes.</p> </div> 2
3
4
Vue.createApp({ data() { return { counter: 0 } } }).mount('#basic-event') 2
3
4
5
6
7
Resultado:
Veja o exemplo Exemplo básico de manipulação de eventos por vuejs-br (@vuejs-br) no CodePen.
# Métodos em Manipuladores
A lógica para muitos manipuladores de evento será mais complexa, portanto, manter diretamente código JavaScript no valor do atributo v-on não é viável. É por isso que v-on também pode aceitar o nome de um método que você gostaria de chamar.
Por Exemplo:
<div id="event-with-method"> <!-- `greet` é o nome de um método definido abaixo --> <button @click="greet">Cumprimentar</button> </div> 2
3
4
Vue.createApp({ data() { return { name: 'Vue.js' } }, methods: { greet(event) { // `this` dentro de métodos aponta para a atual instância Vue ativa alert('Olá ' + this.name + '!') // `event` é o evento DOM nativo if (event) { alert(event.target.tagName) } } } }).mount('#event-with-method') 2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Resultado:
Veja o exemplo Exemplo de manipulação de eventos com um método por vuejs-br (@vuejs-br) no CodePen.
# Chamada Direta de Métodos
Em vez de interligar o evento diretamente ao nome de um método, também podemos chamar métodos diretamente com uma instrução JavaScript:
<div id="inline-handler"> <button @click="say('oi')">Diga oi</button> <button @click="say('tchau')">Diga tchau</button> </div> 2
3
4
Vue.createApp({ methods: { say(message) { alert(message) } } }).mount('#inline-handler') 2
3
4
5
6
7
Resultado:
Veja o exemplo Exemplo de evento com chamada direta de métodoo por vuejs-br (@vuejs-br) no CodePen.
Às vezes, também precisamos acessar o evento original do DOM em um manipulador. Você pode passá-lo à um método usando a variável especial $event:
<button @click="warn('O formulário ainda não pode ser enviado.', $event)"> Enviar </button> 2
3
// ... methods: { warn(message, event) { // agora temos acesso ao evento nativo if (event) { event.preventDefault() } alert(message) } } 2
3
4
5
6
7
8
9
10
# Múltiplos Manipuladores de Eventos
Você pode ter vários métodos em um manipulador de eventos separados por vírgula, desta forma:
<!-- ambos one() e two() serão executados no clique do botão --> <button @click="one($event), two($event)"> Enviar </button> 2
3
4
// ... methods: { one(event) { // lógica do primeiro manipulador... }, two(event) { // lógica do segundo manipulador... } } 2
3
4
5
6
7
8
9
# Modificadores de Evento
É muito comum precisar chamar event.preventDefault() ou event.stopPropagation() em manipuladores de eventos. Embora possamos fazer isto facilmente dentro de métodos, seria melhor se os métodos pudessem lidar apenas com a lógica dos dados, em vez de ter que lidar com detalhes de eventos DOM.
Para resolver esse problema, Vue fornece modificadores de evento para v-on. É só se lembrar que modificadores são sufixos da diretiva, denotados por um ponto.
.stop.prevent.capture.self.once.passive
<!-- a propagação do evento click será interrompida --> <a @click.stop="doThis"></a> <!-- o evento submit deixará de recarregar a página --> <form @submit.prevent="onSubmit"></form> <!-- modificadores podem ser encadeados --> <a @click.stop.prevent="doThat"></a> <!-- é possível utilizar apenas o modificador --> <form @submit.prevent></form> <!-- usar modo de captura ao adicionar o evento --> <!-- ou seja, um evento em um elemento interno é tratado aqui antes de ser tratado por aquele elemento --> <div @click.capture="doThis">...</div> <!-- só aciona o manipulador se event.target é o próprio elemento --> <!-- isto é, não aciona a partir de um elemento filho --> <div @click.self="doThat">...</div> 2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Nota
A ordem importa ao utilizar modificadores pois o código relevante é gerado na mesma ordem. Desta forma, @click.prevent.self prevenirá a ação padrão do clique no próprio elemento e seus filhos, enquanto @click.self.prevent prevenirá apenas a ação padrão de cliques no próprio elemento.
<!-- o evento click será disparado apenas uma vez --> <a @click.once="doThis"></a> 2
Diferente dos outros modificadores, que são exclusivos para eventos nativos, o modificador .once também pode ser usado em eventos de componentes. Se você ainda não leu sobre componentes, não se preocupe com isso neste momento.
Vue também oferece o modificador .passive, correspondendo à opção passive do addEventListener (opens new window).
<!-- o comportamento padrão do evento _scroll_ (rolar) acontecerá --> <!-- imediatamente, ao invés de aguardar `onScroll` completar --> <!-- para descobrir se ele chama `event.preventDefault()` --> <div @scroll.passive="onScroll">...</div> 2
3
4
O .passive é especialmente útil para otimizar desempenho em dispositivos móveis.
Nota
Não use .passive e .prevent juntos, pois .prevent será ignorado e seu navegador provavelmente exibirá um aviso. Lembre-se, .passive comunica ao navegador que você não quer prevenir o comportamento padrão do evento.
# Modificadores de Teclado
Quando escutamos eventos do teclado, precisamos muitas vezes verificar a ocorrência de teclas específicas. O Vue também permite a adição de modificadores v-on ou @ ao escutar eventos de teclado:
<!-- só chama `vm.submit()` quando o `key` é `Enter` --> <input @keyup.enter="submit" /> 2
Você pode usar diretamente qualquer nome de tecla válido exposto via KeyboardEvent.key (opens new window) como modificadores, convertendo-os em kebab-case.
<input @keyup.page-down="onPageDown" /> No exemplo acima, o manipulador só será chamado se $event.key for igual a 'PageDown'.
# Apelidos de Teclas
Vue fornece apelidos para os códigos de teclas mais comuns:
.enter.tab.delete(captura tanto "Delete" quanto "Backspace").esc.space.up.down.left.right
# Modificadores de Teclas do Sistema
Você pode utilizar os seguintes modificadores para acionar eventos de mouse ou teclado apenas quando o modificador correspondente estiver pressionado:
.ctrl.alt.shift.meta
Nota
Nos teclados Macintosh, meta é a tecla de comando (⌘). Nos teclados Windows, meta é a tecla Windows (⊞). Nos teclados Sun Microsystems, meta é marcada como um diamante sólido (◆). Em alguns teclados, especificamente em máquinas MIT e Lisp e suas sucessoras, assim como o teclado Knight e teclados space-cadet, meta é marcada como “META”. Em teclados Symbolics, meta é marcada como “META” ou “Meta”.
Por exemplo:
<!-- Alt + Enter --> <input @keyup.alt.enter="clear" /> <!-- Ctrl + Click --> <div @click.ctrl="doSomething">Faça alguma coisa</div> 2
3
4
5
TIP
Teclas modificadoras são diferentes de teclas comuns, e quando utilizadas com eventos keyup, precisam estar pressionadas quando o evento é emitido. Em outras palavras, keyup.ctrl só vai disparar se você soltar alguma tecla enquanto ainda estiver segurando ctrl. E não irá disparar se você soltar a tecla ctrl sozinha.
# Modificador .exact
O modificador .exact permite controlar a exata combinação de modificadores de sistema que deve ser pressionada para que o gatilho dispare.
<!-- dispara mesmo se Alt ou Shift também estiverem pressionados --> <button @click.ctrl="onClick">A</button> <!-- dispara somente quando Ctrl (e nenhuma outra tecla) for pressionado --> <button @click.ctrl.exact="onCtrlClick">A</button> <!-- dispara somente se não houverem teclas do sistema pressionadas --> <button @click.exact="onClick">A</button> 2
3
4
5
6
7
8
# Modificadores dos Botões do Mouse
.left.right.middle
Estes modificadores restringem o manipulador à eventos disparados por um botão específico do mouse.
# Por Que Escutas no HTML?
Você pode estar pensando que esta abordagem de escutas de evento viola as boas e velhas práticas sobre "separação de responsabilidades". Fique tranquilo - como todas as funções de manipuladores e expressões Vue são estritamente ligadas ao ViewModel que está manipulando o modo de exibição atual, essa abordagem não causará qualquer dificuldade de manutenção. Na verdade, há vários benefícios em usar v-on ou @:
É mais fácil localizar as implementações de função de manipulador dentro de seu código JS percorrendo o template HTML.
Como você não tem que manualmente anexar escutas à eventos em JS, seu código de ViewModel pode conter apenas a lógica pura e ser livre de manipulação do DOM. Isto torna mais fácil de testar.
Quando um ViewModel é destruído, todas as escutas de eventos são removidas automaticamente. Você não precisa se preocupar em removê-las explicitamente.