Atualizado: 12/01/2025

Vue.js Fluxo de Dados Unidirecional

No Vue.js, os dados fluem em uma única direção, do componente pai para os componentes filhos, por meio de props. Quando o componente pai altera um valor, os componentes filhos que recebem esse valor por props são atualizados automaticamente. No entanto, um componente filho não pode modificar diretamente uma prop, pois props são apenas para leitura.

Se um componente filho tentar alterar diretamente um valor recebido por props, o Vue emitirá um aviso no console do navegador e a alteração não será aplicada.

No exemplo abaixo, um valor é passado do componente pai para o filho, que tenta modificá-lo por meio de um campo de entrada:

<!DOCTYPE html>
<html>
<head>
    <title>Componentes Vue.js</title>
    <meta charset="utf-8" />
    <script src="https://unpkg.com/vue"></script>
</head>
<body>
    <div id="app">
        <h2>Hello, {{ name }}</h2>
        <user-edit :user="name"></user-edit>
    </div>

    <script>
        const app = Vue.createApp({
            data() {
                return { name: 'Tom' };
            }
        });

        app.component('user-edit', {
            props: ["user"],
            template: '<div><input type="text" v-model="user" /><p>Name: {{ user }}</p></div>'
        });

        app.mount('#app');
    </script>
</body>
</html>

O componente user-edit recebe o valor name por meio de props. O campo de entrada está vinculado a esse valor com v-model, o que sugere que ele pode ser alterado. No entanto, como props são apenas para leitura, qualquer tentativa de alteração resultará em um aviso no console do navegador.

O componente user-edit recebe o valor name por meio de props. O campo de entrada está vinculado a esse valor com v-model, o que sugere que ele pode ser alterado. No entanto, como props são apenas para leitura, qualquer tentativa de alteração resultará em um aviso no console do navegador.

Exemplo de warning ao alterar props em Vue.js

Se for necessário permitir que o componente filho modifique o valor recebido por props, a solução é criar uma variável local dentro do data(), que recebe o valor inicial de props, mas não o modifica diretamente:

<!DOCTYPE html>
<html>
<head>
    <title>Componentes Vue.js</title>
    <meta charset="utf-8" />
    <script src="https://unpkg.com/vue"></script>
</head>
<body>
    <div id="app">
        <h2>Hello, {{ name }}</h2>
        <user-edit :user="name"></user-edit>
    </div>

    <script>
        const app = Vue.createApp({
            data() {
                return { name: 'Tom' };
            }
        });

        app.component('user-edit', {
            props: ["user"],
            data() {
                return { userName: this.user };
            },
            template: '<div><input type="text" v-model="userName" /><p>Name: {{ userName }}</p></div>'
        });

        app.mount('#app');
    </script>
</body>
</html>

Agora, todas as modificações feitas no campo de entrada afetam apenas a variável userName dentro do componente user-edit, sem alterar o valor original recebido por props.

Exemplo de alteração de props em Vue.js

Sincronizando Valores Entre Pai e Filho

A abordagem acima resolve o problema de tentar alterar diretamente uma prop em um componente filho. No entanto, ela apresenta um problema: se o valor da prop user for atualizado pelo componente pai, userName dentro do componente filho não refletirá essa mudança automaticamente.

Se for necessário manter os valores sincronizados quando o componente pai atualiza uma prop, a melhor abordagem é usar um watcher (watch). Ele observa mudanças no valor de props e atualiza a variável local quando necessário:

<!DOCTYPE html>
<html>
<head>
    <title>Componentes Vue.js</title>
    <meta charset="utf-8" />
    <script src="https://unpkg.com/vue"></script>
</head>
<body>
    <div id="app">
        <div>
            <h3>Vue App</h3>
            <input type="text" v-model="name" />
            <p>Hello, {{ name }}</p>
        </div>
        <user-edit :user="name"></user-edit>
    </div>

    <script>
        const app = Vue.createApp({
            data() {
                return { name: 'Tom' };
            }
        });

        app.component('user-edit', {
            props: ["user"],
            data() {
                return { userName: this.user };
            },
            watch: { 
                user(newVal) {
                    this.userName = newVal;
                }
            },
            template: '<div><h3>Component</h3><input type="text" v-model="userName" /><p>User name: {{ userName }}</p></div>'
        });

        app.mount('#app');
    </script>
</body>
</html>

O watch monitora a prop user. Sempre que o valor dela mudar no componente pai, o valor de userName dentro do componente filho é atualizado para refletir essa mudança. Isso mantém a sincronização entre o estado do componente pai e o estado interno do componente filho.

Exemplo de uso de watcher em Vue.js
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