# 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
Como componentes e props, nomes de eventos fornecem uma transformação automática de maiúsculas e minúsculas. Se você emitir um evento do componente filho em camelCase, poderá adicionar um escutador em kebab-case no pai:
this.$emit('myEvent')
<my-component @my-event="doSomething"></my-component>
Assim como com a escrita de props, recomendamos o uso de escutadores de evento em kebab-case ao usar templates no DOM.
# Definindo Eventos Customizados
Os eventos emitidos podem ser definidos no componente através da opção emits
.
app.component('custom-form', {
emits: ['inFocus', '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 do tipo 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(email, password) {
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:
app.component('my-component', {
props: {
title: String
},
emits: ['update:title'],
template: `
<input
type="text"
:value="title"
@input="$emit('update:title', $event.target.value)">
`
})
2
3
4
5
6
7
8
9
10
11
12
# 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
app.component('user-name', {
props: {
firstName: String,
lastName: String
},
emits: ['update:firstName', 'update:lastName'],
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
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 de 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="myText"
.
<my-component v-model.capitalize="myText"></my-component>
app.component('my-component', {
props: {
modelValue: String,
modelModifiers: {
default: () => ({})
}
},
emits: ['update:modelValue'],
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
17
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: () => ({})
}
},
emits: ['update:modelValue'],
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
32
Para os vínculos v-model
com argumentos, o nome da propriedade gerada será arg + "Modifiers"
:
<my-component v-model:description.capitalize="myText"></my-component>
app.component('my-component', {
props: ['description', 'descriptionModifiers'],
emits: ['update:description'],
template: `
<input type="text"
:value="description"
@input="$emit('update:description', $event.target.value)">
`,
created() {
console.log(this.descriptionModifiers) // { capitalize: true }
}
})
2
3
4
5
6
7
8
9
10
11
12