Atualizado: 28/03/2025

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.

Renderizando lista com slots com escopo no Vue.js

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-bind dentro do slot.

  • Quando o slot não possui nome, o Vue o trata como default, e o pai deve usar v-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.

Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com