# Eventos Customizados
Esta página assume que você já leu o Básico sobre Componentes. Leia lá antes se você está iniciando com componentes.
# Nomes de Eventos
Diferente de componentes e propriedades, os nomes de eventos não convertem automaticamente maiúsculas e minúsculas. Em vez disso, o nome de um evento emitido deve corresponder exatamente ao nome usado para escutar este evento. Por exemplo, se emitir um evento com nome em camelCase:
this.$emit('myEvent')
Escutar com kebab-case não funcionará:
<!-- Não funcionará -->
<my-component @my-event="doSomething"></my-component>
2
Considerando que os nomes de eventos nunca serão usados como nomes de variáveis ou de propriedades no JavaScript, não há razão para usar camelCase ou PascalCase. Além disso, escutadores de eventos v-on
dentro dos templates DOM serão automaticamente transformados em minúsculas (devido ao HTML ser insensível à maiúsculas e minúsculas), então @myEvent
se tornará @myevent
-- fazendo myEvent
impossível de ser escutado.
Por estas razões, nós recomendamos que você sempre use kebab-case para nomes de eventos.
# Definindo Eventos Customizados
Os eventos emitidos podem ser definidos no componente através da opção emits
.
app.component('custom-form', {
emits: ['in-focus', 'submit']
})
2
3
Quando um evento nativo (por exemplo, click
) for definido na opção emits
, o evento do componente será usado ao invés de um escutador de evento nativo.
DICA
Recomenda-se definir todos os eventos emitidos para documentar melhor como o componente deve funcionar.
# Validar Eventos Emitidos
Semelhante à validação de propriedades, um evento emitido pode ser validado se for definido com a sintaxe Object em vez da sintaxe Array.
Para adicionar validação, o evento recebe uma função que recebe os argumentos passados para a chamada $emit
e retorna um booleano para indicar se o evento é válido ou não.
app.component('custom-form', {
emits: {
// Sem validação
click: null,
// Validar evento submit
submit: ({ email, password }) => {
if (email && password) {
return true
} else {
console.warn('Argumentos inválidos para o evento submit!')
return false
}
}
},
methods: {
submitForm() {
this.$emit('submit', { email, password })
}
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Argumentos do v-model
Por padrão, em um componente o v-model
usa modelValue
como propriedade e update:modelValue
como evento. Podemos modificar esses nomes passando um argumento para v-model
:
<my-component v-model:title="bookTitle"></my-component>
Nesse caso, o componente filho espera a propriedade title
e emite o evento update:title
para sincronizar:
const app = Vue.createApp({})
app.component('my-component', {
props: {
title: String
},
template: `
<input
type="text"
:value="title"
@input="$emit('update:title', $event.target.value)">
`
})
2
3
4
5
6
7
8
9
10
11
12
13
<my-component v-model:title="bookTitle"></my-component>
# Múltiplos Vínculos v-model
Aproveitando a capacidade de direcionar uma determinada propriedade e evento como aprendemos antes em argumentos do v-model
, agora podemos criar múltiplos vínculos de v-model
em uma única instância do componente.
Cada v-model
será sincronizado com uma propriedade diferente, sem a necessidade de opções extras no componente:
<user-name
v-model:first-name="firstName"
v-model:last-name="lastName"
></user-name>
2
3
4
const app = Vue.createApp({})
app.component('user-name', {
props: {
firstName: String,
lastName: String
},
template: `
<input
type="text"
:value="firstName"
@input="$emit('update:firstName', $event.target.value)">
<input
type="text"
:value="lastName"
@input="$emit('update:lastName', $event.target.value)">
`
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Veja o exemplo Múltiplos v-models por L. Tonet (@lucianotonet) no CodePen.
# Manipulando Modificadores do v-model
Quando estávamos aprendendo sobre interligações em elementos input, vimos que v-model
tem modificadores embutidos - .trim
, .number
e .lazy
. Em alguns casos, entretanto, você também pode querer adicionar seus próprios modificadores personalizados.
Vamos criar um modificador personalizado de exemplo, capitalize
, que coloca em maiúscula a primeira letra da string fornecida pela vinculação v-model
.
Modificadores adicionados ao v-model
de um componente serão fornecidos ao componente por meio da propriedade modelModifiers
. No exemplo abaixo, criamos um componente que contém uma propriedade modelModifiers
cujo padrão é um objeto vazio.
Observe que quando o gatilho do ciclo de vida created
do componente é acionado, a propriedade modelModifiers
contém capitalize
e seu valor é true
- devido ao fato de ser definido na vinculação v-model.capitalize="bar"
.
<my-component v-model.capitalize="bar"></my-component>
app.component('my-component', {
props: {
modelValue: String,
modelModifiers: {
default: () => ({})
}
},
template: `
<input type="text"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)">
`,
created() {
console.log(this.modelModifiers) // { capitalize: true }
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Agora que temos nossa propriedade configurada, podemos verificar as chaves do objeto modelModifiers
e escrever um manipulador para alterar o valor emitido. No código a seguir, colocaremos a string em maiúscula sempre que o elemento <input />
disparar um evento input
.
<div id="app">
<my-component v-model.capitalize="myText"></my-component>
{{ myText }}
</div>
2
3
4
const app = Vue.createApp({
data() {
return {
myText: ''
}
}
})
app.component('my-component', {
props: {
modelValue: String,
modelModifiers: {
default: () => ({})
}
},
methods: {
emitValue(e) {
let value = e.target.value
if (this.modelModifiers.capitalize) {
value = value.charAt(0).toUpperCase() + value.slice(1)
}
this.$emit('update:modelValue', value)
}
},
template: `<input
type="text"
:value="modelValue"
@input="emitValue">`
})
app.mount('#app')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Para os vínculos v-model
com argumentos, o nome da propriedade gerada será arg + "Modifiers"
:
<my-component v-model:foo.capitalize="bar"></my-component>
app.component('my-component', {
props: ['foo', 'fooModifiers'],
template: `
<input type="text"
:value="foo"
@input="$emit('update:foo', $event.target.value)">
`,
created() {
console.log(this.fooModifiers) // { capitalize: true }
}
})
2
3
4
5
6
7
8
9
10
11