# Composición
# mixins
Tipo:
Array<Object>
Detalles:
La opción
mixins
acepta una matriz de objetos mixin. Estos objetos mixin pueden contener opciones de instancia como objetos normales de instancias, y serán fundidos contra las opciones eventuales utilizando la cierta lógica para fundir opciones. Por ejemplo, si su mixin contiene un hookcreated
y el componente mismo también tiene uno, ambos funciones serán llamados.Los hooks mixin son llamados en el order que son proporcionados, y llamados antes de los propios hooks del componente.
INFO
En Vue 2, mixins fueron el principal mecanismo para crear fragmentos reutilizables de lógica de componente. Mientras mixins siguen siendo soportado en Vue 3, la API de Composición ahora es el enfoque preferido para la reutilización de código entre componentes.
Ejemplo:
const mixin = { created() { console.log(1) } } createApp({ created() { console.log(2) }, mixins: [mixin] }) // => 1 // => 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15Vea también: Mixins
# extends
Tipo:
Object
Detalles:
Permite un componente de extender otro, heredando sus opciones de componente.
Desde una perspectiva de implementación,
extends
es casi igual amixins
. El componente especificado porextends
será tratado como si sea el primero mixin.Sin embargo,
extends
ymixins
expresan intenciones diferentes. La opcionmixins
es principalmente utilizada para componer fragmentos de funcionalidad, mientrasextends
se ocupa principalmente de herencia.Como con
mixins
, cualquieras opciones serán fundidas utilizando la estrategia relevante de fundir.Ejemplo:
const CompA = { ... } const CompB = { extends: CompA, ... }
1
2
3
4
5
6
# provide / inject
Tipo:
- provide:
Object | () => Object
- inject:
Array<string> | { [key: string]: string | Symbol | Object }
- provide:
Detalles:
Este par de opciones son utilizadas juntos para permitir un componente ancestro para servir como un inyector de dependencias para todos sus descendientes, sin tener en cuenta la profundidad de jerarquía de componente, siempre y cuando son en la misma cadena padre. Si está familizar con React, este es muy similar a la característica
context
de React.La opción
provide
debería ser un objeto u una función que retorna un objeto. Este objeto contiene las propiedades que son disponibles para inyección a sus descendientes. Puede utilizar los Symbols de ES2015 como claves en este objeto, pero solo en entornos que originalmente soportanSymbol
yReflect.ownKeys
.La opción
inject
debería ser cualquier de las siguientes:- una matriz de cadenas de caracteres, o
- un objeto dónode las claves son los nombres locales de vinculación y el valor es cualquier de estos:
- la clave (cadena de caracteres o Symbol) para buscar en inyecciones disponibles, o
- un objeto dónde:
- la propiedad
from
es la clave (cadena de caracteres o Symbol) para buscar en inyecciones disponibles, y - la propiedad
default
es utilizada como un valor por defecto (fallback)
- la propiedad
Note que las vinculaciones de
provide
yinject
NO son reactivas. Este es deliberado. Sin embargo, si pasa un objeto reactivo, las propiedades de ese objeto mantienen reactivas.Ejemplo:
// el componente padre proporciona 'foo' const Provider = { provide: { foo: 'bar' } // ... } // el componente hijo inyecta 'foo' const Child = { inject: ['foo'], created() { console.log(this.foo) // => "bar" } // ... }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16Con Symbols de ES2015, función
provide
y objetoinject
:const s = Symbol() const Provider = { provide() { return { [s]: 'foo' } } } const Child = { inject: { s } // ... }
1
2
3
4
5
6
7
8
9
10
11
12
13
14Utilizando un valor inyectado como el valor por defecto para una prop:
const Child = { inject: ['foo'], props: { bar: { default() { return this.foo } } } }
1
2
3
4
5
6
7
8
9
10Utilizando un valor inyectado como una entrada de dato:
const Child = { inject: ['foo'], data() { return { bar: this.foo } } }
1
2
3
4
5
6
7
8Las inyecciones pueden ser opcionales con valores por defecto:
const Child = { inject: { foo: { default: 'foo' } } }
1
2
3
4
5Si necesita inyectar una propiedad con un diferente nombre, utilice
from
para denotar la propiedad origional:const Child = { inject: { foo: { from: 'bar', default: 'foo' } } }
1
2
3
4
5
6
7
8Similar a los valores por defecto de prop, necesita utilizar una función de fábrica para los valores que no son primitivos:
const Child = { inject: { foo: { from: 'bar', default: () => [1, 2, 3] } } }
1
2
3
4
5
6
7
8Vea también: Provide / Inject
# setup
- Tipo:
Function
La función setup
es una nueva opción de componente. Sirve como la punta de entrada para utilizar la API de Composición dentro de componentes.
Invocation Timing
setup
es llamado justo después de la resolución inicial de props cuando una instancia de componente sea creada. Lo mismo como el ciclo de vida, es llamado antes del hook beforeCreate hook.Uso con Plantillas
Si
setup
retorna un objeto, las propiedades del objeto serán fundidas en el contexto de renderización para la plantilla del componente:<template> <div>{{ count }} {{ object.foo }}</div> </template> <script> import { ref, reactive } from 'vue' export default { setup() { const count = ref(0) const object = reactive({ foo: 'bar' }) // exponer a la plantilla return { count, object } } } </script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20Note que refs retornadas de
setup
son automáticamente desenvueltas cuand accesadas en la plantilla, así que no es necesario escribir.value
en las plantillas.Uso con Funciones Render / JSX
setup
puede también retornar una función render, lo que puede directamente aprovecha estados reactivos declarados en el mismo alcance:import { h, ref, reactive } from 'vue' export default { setup() { const count = ref(0) const object = reactive({ foo: 'bar' }) return () => h('div', [count.value, object.foo]) } }
1
2
3
4
5
6
7
8
9
10Argumentos
La función recibe las props resueltas como su primer argumento:
export default { props: { name: String }, setup(props) { console.log(props.name) } }
1
2
3
4
5
6
7
8Note que este objeto
props
es reactivo, es decir, es actualizado cuando nuevas props son pasados adentro, y puede ser observado y reaccionado según utilizarwatchEffect
owatch
:export default { props: { name: String }, setup(props) { watchEffect(() => { console.log(`El nombre es: ` + props.name) }) } }
1
2
3
4
5
6
7
8
9
10Sin embargo, NO desestructure el objeto
props
, debido a que se perderá la reactividad:export default { props: { name: String }, setup({ name }) { watchEffect(() => { console.log(`El nombre es: ` + name) // ¡Será reactivo! }) } }
1
2
3
4
5
6
7
8
9
10El objeto
props
es inmutable para código del lado de usuario durante desarrollo (lanzará advertencias si el código de usuario trate de mutarlo).El segundo argumento proporciona un objeto de contexto que exponga varios objetos y funciones que podrían ser útiles en
setup
:const MyComponent = { setup(props, context) { context.attrs context.slots context.emit context.expose } }
1
2
3
4
5
6
7
8attrs
,slots
, yemit
son equivalentes a las propiedades de instancia$attrs
,$slots
, y$emit
, respectivamente.attrs
yslots
son proxies a los valores correspondientes en la instancia internal de componente. Este asegura que siempre exponen los últimos valores, incluso detrás actualizaciones, así que podemos desestructurarlos sin preocuparnos por acceder una referencia obsoleta:const MyComponent = { setup(props, { attrs }) { // Una función que podría ser llamada en una fase posterior function onClick() { console.log(attrs.foo) // garantizado como la última referencia } } }
1
2
3
4
5
6
7
8expose
, agregado en Vue 3.2, es una función que permite especificar propiedades para ser expuestas mediante la instancia pública de componente. Por defecto, la instancia pública de componente recuperada utilizando refs,$parent
, o$root
es equivalente a la instancia internal utilizada por la plantilla. Llamarexpose
creará una instancia pública separada con las propiedades especificadas:const MyComponent = { setup(props, { expose }) { const count = ref(0) const reset = () => count.value = 0 const increment = () => count.value++ // solo _reset_ será disponible externamente, p. ej. mediante $refs expose({ reset }) // Internamente, la plantilla tiene acceso a _count_ y _increment_ return { count, increment } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15Hay un número de razones para poner
props
como un primero argumento separado en vez de incluirlo en el contexto:Es mucho más común para un componente para utilizar
props
que otras propiedades, y muy a menudo un componente utiliza sóloprops
.Tener
props
como un argumento separado lo hace más fácil para tiparlo individualmente sin confundir con los tipos de otras propiedades en el contexto. También lo hace posible mantener una signatura consistente entresetup
,render
y componentes planos funcionales con soporte de TSX.
Vea también: API de Composición