# 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.