# Eventos Personalizados
Esta página asume que usted ya ha leído Básicos de Componentes. Léalo primero si usted es nuevo con componentes.
# Nombre de eventos
Como los componentes y props, los nombres de eventos proporcionan una transformación automática de casos. Si emite un evento desde el componente secundario con un nombre de camelCase, será capaz de agregar un escuchador de kebab-case en el componente padre.
this.$emit('myEvent')
<my-component @my-event="doSomething"></my-component>
Como con Casos de Props, recomendamos utilizar escuchadores de eventos de kebab-case cuando está utilizando plantillas en DOM. Si está utilizando plantillas de cadena de caracteres, esta limitación no se aplica.
# Definir eventos personalizados
Los eventos emitidos pueden ser definido en el componente mediante la opción emits
.
app.component('custom-form', {
emits: ['inFocus', 'submit']
})
2
3
Cuando un evento nativo (p. ej. click
) está definido en la opción emits
, el evento de componente será utilizado en vez de un escuchador de evento nativo.
TIP
Es recomendado definir todos eventos emitidos para documentar mejor cómo un componente debería funcionar.
# Validar eventos emitidos
Similar a las validaciones de props, un evento emitido puede ser validado si es definido con la sintaxis de objeto en vez de matriz.
Para agregar validación, una función está asignado al evento, la que recibe los argumentos pasados a la llamada de $emit
y retorna un valor booleano para indicar si el evento es válido o no.
app.component('custom-form', {
emits: {
// no validación
click: null,
// Validar el evento _submit_
submit: ({ email, password }) => {
if (email && password) {
return true
} else {
console.warn('¡La carga del evento submit es inválida!')
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 de v-model
Por defecto, v-model
de un componente utiliza modelValue
como la prop y update:modelValue
como el evento. Podemos modificar estes nombres pasando un argumento a v-model
:
<my-component v-model:title="bookTitle"></my-component>
En este caso, el componente secundario esperará una prop title
y emitirá 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últiples vinculaciones de v-model
Al aprovechar la capacidad para dirigir una prop u evento particular como aprendemos antes con argumentos de v-model
, podemos ahora crear múltiples vinculaciones de v-model
en una sola instancia de componente.
Cada v-model
será sincronizado con una prop diferente, sin la necesidad de opciones adicionales en el 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
See the Pen Múltiples directivas de v-model by Vue (@Vue) on CodePen.
# Manejar modificadores de v-model
Cuando estabamos aprendiendo sobre las vinculaciones de entradas de formularios, vimos que v-model
tiene modificadores integrados - .trim
, .number
y .lazy
. En algunos casos, sin embargo, querría también agregar sus propios modificadores personalizados.
Creemos un ejemplo de modificador personalizado, capitalize
, lo que pone en mayúscula la primera letra de la cadena de caracteres proporcionada por la vinculación de v-model
.
Los modificadores agregados a v-model
de un componente serán proporcionados al componente mediante la prop modelModifiers
. En el siguiente ejemplo, hemos creado un componente que contiene una prop modelModifiers
que utiliza un objeto vacío como su valor por defecto.
Note que cuando se activa el hook de ciclo de vida created
del componente, la prop modelModifiers
contiene capitalize
y su valor es true
- debido a que está establecido en la vinculación de v-model
, es decir, 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
Ahora que tenemos nuestra prop establecida, podemos probar las claves del objeto modelModifiers
y escribir un manejador para cambiar el valor emitido. En el código abajo vamos a poner en mayúscula la primera letra de la cadena de caracteres cada vez que el elemento <input />
dispare un 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 las vinculaciones de v-model
con argumentos, el nombre generado de la prop 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