Slots com escopo no Vue.js
Em determinados cenários, é necessário acessar dados internos de um componente filho no conteúdo que o componente pai envia para ele. Um caso comum ocorre quando se tenta acessar dados definidos no filho diretamente dentro do corpo do componente pai. Considere o seguinte código:
Componente pai:
<div id="app">
<user>
<h3>Dados do usuário</h3>
<p>Nome: {{ user.name }}</p>
<p>Idade: {{ user.age }}</p>
</user>
</div>Componente filho:
const app = Vue.createApp({});
app.component("user", {
data() {
return { user: { name: "Tom", age: 36 } };
},
template: `<div><slot></slot></div>`,
});
app.mount("#app");Esse código não funciona porque o componente pai não tem acesso ao objeto user, que está definido apenas dentro do componente user. As expressões {{ user.name }} e {{ user.age }} estão fora do escopo e, por isso, não produzem nenhum valor visível.
Para resolver esse tipo de situação, pode-se recorrer aos slots com escopo (scoped slots). Esse recurso permite que o componente filho envie dados ao conteúdo que o pai define dentro do slot. Os dados disponibilizados pelo filho ficam acessíveis apenas dentro desse escopo.
No componente pai, o slot é declarado dentro de um <template> usando a diretiva v-slot. Essa diretiva recebe um identificador que representa os dados enviados pelo componente filho.
A seguir, um exemplo funcional usando scoped slots:
<!DOCTYPE html>
<html>
<head>
<title>Slots Vue 3</title>
<meta charset="utf-8" />
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<user>
<template v-slot:default="props">
<h3>Dados do usuário</h3>
<p>Nome: {{ props.userinfo.name }}</p>
<p>Idade: {{ props.userinfo.age }}</p>
</template>
</user>
</div>
<script>
const app = Vue.createApp({});
app.component("user", {
data() {
return { user: { name: "Tom", age: 36 } };
},
template: `
<div>
<slot v-bind:userinfo="user"></slot>
</div>
`,
});
app.mount("#app");
</script>
</body>
</html>Neste exemplo, o componente user disponibiliza o objeto user para o slot através de v-bind:userinfo="user". O componente pai define o conteúdo do slot padrão usando v-slot:default="props". Dessa forma, os dados são acessados por meio de props.userinfo.
Como o slot não possui um nome explícito, o Vue o trata como default, e a diretiva correspondente no pai é v-slot:default. O identificador props representa o objeto com os dados transmitidos e pode ter qualquer nome, desde que seja coerente com o uso interno.
Esse padrão também pode ser aplicado a listas, permitindo que o componente pai controle a estrutura visual de cada item:
<!DOCTYPE html>
<html>
<head>
<title>Slots Vue 3</title>
<meta charset="utf-8" />
<script src="https://unpkg.com/vue"></script>
</head>
<body>
<div id="app">
<userslist>
<template v-slot:userdetails="props">
<div>
<p>Nome: {{ props.userinfo.name }}</p>
<p>Idade: {{ props.userinfo.age }}</p>
</div>
</template>
</userslist>
</div>
<script>
const app = Vue.createApp({});
app.component("userslist", {
data() {
return {
users: [
{ name: "Tom", age: 36 },
{ name: "Sam", age: 39 },
{ name: "Bob", age: 25 },
],
};
},
template: `
<ul>
<li v-for="user in users">
<slot name="userdetails" v-bind:userinfo="user"></slot>
</li>
</ul>
`,
});
app.mount("#app");
</script>
</body>
</html>O componente userslist percorre o array users e, para cada item, dispara o slot nomeado userdetails, enviando o respectivo objeto pelo atributo v-bind:userinfo="user".
O componente pai define o conteúdo do slot userdetails usando a diretiva v-slot:userdetails="props", acessando os dados de cada usuário por meio de props.userinfo.
Esse padrão permite que o pai controle completamente a estrutura e a apresentação dos dados, enquanto o componente filho se responsabiliza apenas pela lógica de dados e repetição.

Resumo
- Scoped slots permitem que um componente filho envie dados ao conteúdo definido no slot pelo componente pai.
- O slot é declarado no pai com
<template v-slot:nome="variável">. - Os dados são enviados pelo filho com
v-binddentro do slot. - Quando o slot não possui nome, o Vue o trata como
default, e o pai deve usarv-slot:default. - O pai pode acessar os dados enviados por meio do identificador declarado no
v-slot. - Esse recurso oferece flexibilidade para controlar a estrutura visual no pai enquanto o filho gerencia os dados.
Documentação oficial: