- Aprender
-
Ecosistema
Ayuda
Herramientas
Librerías Oficiales
Noticias
Lista de Recursos
- Equipo
- Apoyar Vue
- Traducciones
Guía
Conocimientos Esenciales
- Instalación
- Introducción
- La instancia Vue
- Sintaxis de Template
- Propiedades Computadas y Observadores
- Enlace Clases y Estilos
- Renderización Condicional
- Renderizado de lista
- Manejo de eventos
- Binding en Formularios
- Conceptos Básicos de Componentes
Transiciones & Animaciones
- Efectos de Transición
Componentes en Profundidad
- Registro de Componente
- Propiedades
- Eventos personalizados
- Slots
- Componentes Dinámicos & Asíncronos
- Handling Edge Cases
- Transiciones de estado
Reusabilidad & Composición
- Mixins
- Directivas Personalizadas
- Funciones de renderizado & JSX
- Plugins
- Filtros
- Publicación en Producción
Herramientas
- Componentes de un Solo Archivo (Single File Components)
- Testing Unitario
- Soporte TypeScript
Escalando la Aplicación
- Enrutamiento
- Administración del Estado
- Renderizado del lado de Servidor
Funcionamiento Interno
- Reactividad en profundidad
Migraciones
- Migración desde Vue 1.x
- Migración desde Vue Router 0.7.x
- Migración de Vuex 0.6.x a 1.0
Meta Documentación
- Comparación con otros frameworks
- Únete a la comunidad Vue.js!
- Conozca al equipo
Slots
Esta página asume que ya ha leído Conceptos Básicos de Componentes. Léalo primero si es nuevo con respecto a componentes.
En 2.6.0 introdujimos una nueva sintaxis unificada (la directiva
v-slot
) para los slots con nombre y scope. Esta sustituye los atributos “slot” y “slot-scope”, que ahora están obsoletos, pero que _no_ han sido eliminados y todavía están documentados aquí. La razón para introducir la nueva sintaxis se describe en este RFC.
Contenido del Slot
Vue implementa una API de distribución de contenido que se modela después del Borrador de especificaciones de componentes web actual, usando el elemento <slot>
para servir como puntos de distribución para el contenido.
Esto le permite componer componentes como este:
<navigation-link url="/profile"> |
Luego en la plantilla para <navigation-link>
, es posible que usted tenga:
<a |
Cuando el componente renderiza, el elemento <slot>
será reemplazado por “Su Perfil”. Los Slots pueden contener cualquier plantilla de código, incluyendo HTML:
<navigation-link url="/profile"> |
O incluso otros componentes:
<navigation-link url="/profile"> |
Si <navigation-link>
no contiene un elemento <slot>
, cualquier contenido que se le pase será simplemente descartado.
Scope de compilación
Cuando desee utilizar datos dentro de un slot, como en:
<navigation-link url="/profile"> |
Ese slot tiene acceso a las mismas propiedades de instancia (es decir, el mismo scope
) que el resto de la plantilla. El slot _no_ tiene acceso al scope de <navigation-link>
. Por ejemplo, intentar acceder a url
no funcionaría:
<navigation-link url="/profile"> |
Como regla, recuerde esto:
Todo en la plantilla de los padres está compilado en el scope de los padres; todo en la plantilla de los hijos está compilado en el scope de los hijos.
Contenido alternativo
Hay casos en que es útil especificar el contenido alternativo (es decir, por defecto) para un slot, que se renderizará solo cuando no se proporcione ningún contenido. Por ejemplo, en un componente <submit-button>
:
<button type="submit"> |
Podríamos querer que el texto “Enviar” se muestre la mayor parte del tiempo dentro del <button>
. Para hacer que “Enviar” sea el contenido alternativo, podemos colocarlo entre las etiquetas <slot>
:
<button type="submit"> |
Ahora, cuando usamos <submit-button>
en un componente padre, sin incluir contenido en el slot:
<submit-button></submit-button> |
renderizará el contenido alternativo, “Enviar”:
<button type="submit"> |
Pero si proporcionamos contenido:
<submit-button> |
Entonces el contenido proporcionado será presentado en su lugar:
<button type="submit"> |
Slots con nombre
Actualizado en 2.6.0+. Ver aquí para la sintaxis obsoleta usando el atributo “slot”.
Hay ocasiones en que es útil tener múltiples slots. Por ejemplo, en un componente hipotético <base-layout>
con la siguiente plantilla:
<div class="container"> |
Para estos casos, el elemento <slot>
tiene un atributo especial, name
, que puede ser usado para definir slots adicionales:
<div class="container"> |
Un <slot>
sin nombre
tiene implícitamente el nombre “default”.
Para proporcionar contenido a los slots con nombre, podemos usar la directiva v-slot
en un <template>
, proporcionando el nombre del slot como argumento de v-slot
:
<base-layout> |
Ahora todo lo que está dentro de los elementos de <template>
se pasará a los slots correspondientes. Cualquier contenido que no esté envuelto en un <template>
usando v-slot
se asume que es para el slot por defecto.
Sin embargo, todavía puede envolver el contenido del slot por defecto en un <template>
si quiere ser explícito:
<base-layout> |
De cualquier manera, el HTML renderizado será:
<div class="container"> |
Note que v-slot
solo puede ser agregado a un <template>
(con una excepción), a diferencia del atributo obsoleto slot
.
Slots con Scope
Actualizado en 2.6.0+. Ver aquí para la sintaxis obsoleta usando el atributo “slot-scope”.
A veces, es útil para el contenido del slot tener acceso a los datos solo disponibles en el componente hijo. Por ejemplo, imagine un componente <current-user>
con la siguiente plantilla:
<span> |
Podríamos querer reemplazar este contenido alternativo para mostrar el nombre del usuario, en lugar del apellido, así:
<current-user> |
No obstante eso no funcionará, porque solo el componente
Para hacer que user esté disponible para el contenido del slot en el padre, podemos vincularlo como un atributo al elemento <slot>
:
<span> |
Las propiedades ligadas a un elemento <slot>
se llaman slots props. Ahora, en el scope del padre, podemos usar v-slot
con un valor para definir un nombre para las propiedades del slot que nos han proporcionado:
<current-user> |
En este ejemplo, hemos elegido nombrar al objeto que contiene todos nuestras propiedades del slot “slotProps”, pero puede usar el nombre que prefiera.
Sintaxis abreviada para los Slots Solitarios por Defecto
En casos como el anterior, cuando solo el slot por defecto se proporciona como contenido, las etiquetas del componente pueden utilizarse como plantilla del slot. Esto nos permite utilizar v-slot
directamente en el componente:
<current-user v-slot:default="slotProps"> |
Esto puede acortarse aún más. Así como se asume que el contenido no especificado es para el slot por defecto, se asume que el v-slot
sin un argumento se refiere al slot por defecto:
<current-user v-slot="slotProps"> |
Observe que la sintaxis abreviada del slot por defecto no puede mezclarse con los slots con nombre, ya que ello daría lugar a una ambigüedad en el slot:
<!-- INVÁLIDO, resultará en una advertencia --> |
Siempre que haya múltiples slots, use la sintaxis completa en el<template>
para todos los slots:
<current-user> |
Desestructuración de las propiedades del Slot
Internamente, los slots con scope funcionan envolviendo el contenido de su scope en una función que pasa un solo argumento:
function (slotProps) { |
Esto significa que el valor de v-slot
puede aceptar cualquier expresión JavaScript válida que pueda aparecer en la posición del argumento de una definición de función. Así que en los entornos compatibles (componentes de un solo archivo o navegadores modernos), también se puede utilizar ES2015 destructuring para sacar propiedades específicas del slot , tales como:
<current-user v-slot="{ user }"> |
Esto puede hacer que la plantilla sea mucho más limpia, especialmente cuando el slot proporciona muchas propiedades. También abre otras posibilidades, como renombrar las propiedades, por ejemplo, de user
a person
:
<current-user v-slot="{ user: person }"> |
Incluso puede definir las alternativas, para ser usadas en caso de que un atributo del slot no esté definido:
<current-user v-slot="{ user = { firstName: 'Guest' } }"> |
Nombre dinámicos de los slots
Nuevo en 2.6.0+
Argumentos dinámicos de la directiva también funcionan en v-slot
, permitiendo la definición de nombres dinámicos en los slots:
<base-layout> |
Nombre abreviados de slots
Nuevo en 2.6.0+
Similar a v-on
y v-bind
, v-slot
también tiene una abreviatura, reemplazando todo antes del argumento (v-slot:
) con el símbolo especial “#”. Por ejemplo, v-slot:header
puede ser reescrito como #header
:
<base-layout> |
Sin embargo, al igual que con otras directivas, la abreviatura solo está disponible cuando se proporciona un argumento. Eso significa que la siguiente sintaxis es inválida:
<!-- Esto activará una advertencia --> |
En cambio, siempre debe especificar el nombre del slot si desea utilizar la abreviatura:
<current-user #default="{ user }"> |
Otros ejemplos
Las propiedades de slot nos permiten convertir los slots en plantillas reutilizables que pueden mostrar diferentes contenidos basados en las propiedades de los inputs. Esto es muy útil cuando se diseña un componente reutilizable que encapsula la lógica de los datos mientras permite al componente padre consumidor personalizar parte de su diseño.
Por ejemplo, estamos implementando un componente <todo-list>
que contiene la lógica de diseño y filtrado para una lista:
<ul> |
En lugar de hard-code cada todo, podemos dejar que el componente padre tome el control haciendo de cada todo un slot, y luego vincular todo
como una propiedad del slot:
<ul> |
Ahora, cuando usamos el componente <todo-list>
, podemos opcionalmente definir un <template>
alternativa para cada elemento todo, pero con acceso a los datos del hijo:
<todo-list v-bind:todos="todos"> |
Sin embargo, incluso esto apenas roza la superficie de lo que los slots con scope son capaces de hacer. Para ejemplos potentes y de la vida real del uso de los slots con scope, recomendamos que se busque en bibliotecas como Vue Virtual Scroller, Vue Promised, y Portal Vue.
Sintaxis obsoleta
La directiva
v-slot
fue introducida en la versión 2.6.0, ofreciendo una API alternativa y mejorada a los, aún soportados, atributosslot
yslot-scope
. El fundamento completo de la introducción delv-slot
se describe en este RFC. Los atributosslot
yslot-scope
continuarán siendo soportados en todas las futuras versiones 2.x, pero están oficialmente obsoletos y serán eventualmente retirados en la versión 3.
Slots con nombre con el atributo slot
Obsoleto en 2.6.0+. Ver aquí para la nueva sintaxis recomendada.
Para pasar contenido a los slots con nombre desde el padre, usa el atributo especial slot
en el <template>
(usando el componente <base-layout>
descrito aquí como ejemplo):
<base-layout> |
O, el atributo slot
también puede ser usado directamente en un elemento normal:
<base-layout> |
Todavía puede haber un slot sin nombre, que es el slot por defecto que sirve como un comodín para cualquier contenido sin slot. En los dos ejemplos anteriores, el HTML renderizado sería:
<div class="container"> |
Slots con scope con el atributo slot-scope
Obsoleto en 2.6.0+. Ver aquí para la nueva sintaxis recomendada.
Para recibir propiedades pasadas a un slot, el componente padre puede usar <template>
con el atributo slot-scope
(usando el <slot-example>
descrito aquí como ejemplo):
<slot-example> |
Aquí, slot-scope
declara el objeto de propiedades recibido como la variable slotProps
, y lo hace disponible dentro del scope del <template>
. Puedes nombrar slotProps
como quieras, de forma similar a como se nombran los argumentos de las funciones en JavaScript.
Aquí slot="default"
puede ser omitido al estar implícito:
<slot-example> |
El atributo slot-scope
también puede ser usado directamente en un elemento sin <template>
(incluyendo componentes):
<slot-example> |
El valor del slot-scope
puede aceptar cualquier expresión JavaScript válida que pueda aparecer en la posición del argumento de una definición de función. Esto significa que en los entornos soportados (componentes de un solo archivo o modern browsers) también se puede utilizar ES2015 destructuring en la expresión, de la siguiente forma:
<slot-example> |
Usando la <todo-list>
descrita aquí como ejemplo, aquí está el uso equivalente usando slot-scope
:
<todo-list v-bind:todos="todos"> |