Dominando o Watch Profundo e Propriedades Observáveis no Vue.js

Monitorando uma Propriedade Específica em Estruturas Aninhadas

Quando trabalhamos com objetos cmoplexos no Vue, frequentemente precisamos observar alterações em propriedades específicas localizadas em níveis mais profundos da estrutura de dados. Em vez de monitorar o objeto inteiro, podemos utilizar a notação de caminho (string) para apontar diretamente para o atributo desejado.


<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <title>Monitoramento Específico</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <p>Nível de Brilho: {{ config.display.brightness }}</p>
    <button @click="config.display.brightness += 10">Aumentar Brilho</button>
</div>
<script>
    new Vue({
        el: '#app',
        data: {
            config: {
                display: {
                    brightness: 50,
                    contrast: 70
                }
            }
        },
        watch: {
            'config.display.brightness': function(novoValor, valorAntigo) {
                console.log(`Brilho alterado de ${valorAntigo} para ${novoValor}`);
            }
        }
    });
</script>
</body>
</html>

Monitoramento Profundo de Todas as Propriedades

Caso seja necessário reagir a qualquer alteração dentro de um objeto aninhado, independentemente de qual propriedade interna foi modificada, devemos ativar o monitoramento profundo. Isso é feito definindo a propriedade deep como true na configuração do observador.


<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <title>Monitoramento Profundo</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <p>Brilho: {{ config.display.brightness }}</p>
    <button @click="config.display.brightness += 10">Aumentar Brilho</button>
    <p>Contraste: {{ config.display.contrast }}</p>
    <button @click="config.display.contrast += 10">Aumentar Contraste</button>
</div>
<script>
    new Vue({
        el: '#app',
        data: {
            config: {
                display: {
                    brightness: 50,
                    contrast: 70
                }
            }
        },
        watch: {
            config: {
                deep: true,
                handler(novoValor, valorAntigo) {
                    console.log('Objeto de configuração atualizado:', novoValor);
                }
            }
        }
    });
</script>
</body>
</html>

Sintaxe Abreviada para o Watch

Se o observador não exigir configurações adicionais como deep, immediate ou um handler nomeado, o Vue permite uma sintaxe mais concisa. Basta atribuir diretamente a função de callback à propriedade que se deseja monitorar.

watch: {
    // Sintaxe completa
    config: {
        handler(novoValor) {
            console.log(novoValor);
        }
    },
    
    // Sintaxe abreviada (equivalente)
    'config.display.brightness'(novoValor) {
        console.log(novoValor);
    }
}

Exemplo Prático: Atualização de Dados com Atraso

O watch é particularmente útil para executar operações assíncronas ou que consomem muitos recursos em resposta a mudanças de estado. No exemplo abaixo, simulamos uma operação com atraso para atualizar um nome completo sempre que o primeiro nome ou o sobrenome forem alterados.


<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <title>Watch Assíncrono</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <label>Nome: <input type="text" v-model="firstName"></label><br>
    <label>Sobrenome: <input type="text" v-model="lastName"></label><br>
    <p>Nome Completo: {{ fullName }}</p>
</div>
<script>
    new Vue({
        el: '#app',
        data: {
            firstName: 'João',
            lastName: 'Silva',
            fullName: 'João Silva'
        },
        watch: {
            firstName(novoValor) {
                setTimeout(() => {
                    this.fullName = `${novoValor} ${this.lastName}`;
                }, 800);
            },
            lastName(novoValor) {
                setTimeout(() => {
                    this.fullName = `${this.firstName} ${novoValor}`;
                }, 800);
            }
        }
    });
</script>
</body>
</html>

Propriedades Computadas vs. Propriedades Watch

Embora ambas reajam a mudanças no estado reativo, computed e watch possuem propósitos distintos. Propriedades computadas são ideais para cálculos síncronos e derivados de outros dados, possuindo cache interno que evita reexecuções desnecessárias. Elas não devem conter efeitos colaterais. Por outro lado, o watch é projetado para executar efeitos colaterais, como requisições assíncronas, manipulação direta do DOM ou atualizações de estado complexas que dependem de múltiplas variáveis ou de operações que não podem ser expressas como uma simples função de retorno síncrona.

Tags: vuejs vue-watch deep-watching reactive-properties computed-properties

Publicado em 7-11 23:57