Sobes.tech
Middle

Como funciona a reatividade no Vue.js?

sobes.tech IA

Resposta da IA

A reatividade no Vue.js baseia-se no padrão de "observador" (Observer).

Quando uma instância do Vue é criada, ela percorre todas as propriedades do objeto data e as transforma em getters e setters usando Object.defineProperty no Vue 2 ou Proxy no Vue 3.

Vue 2:

  • Ao aceder a uma propriedade (getter), o Vue rastreia qual o componente que a está a usar.
  • Ao modificar uma propriedade (setter), o Vue notifica todos os componentes que a estavam a observar para que se atualizem (re-renderizar o template).

Vue 3:

  • Usa Proxy para interceptar todas as operações no objeto (adicionar, remover propriedades, alterar valores, etc.), proporcionando uma reatividade mais completa em comparação com o Vue 2.
  • Graças ao Proxy, a reatividade no Vue 3 não tem as limitações do Vue 2 (não é necessário $set para adicionar novas propriedades).

Componentes-chave da reatividade:

  • Observer: Transforma as propriedades de dados em getters/setters (Vue 2) ou as gere com Proxy (Vue 3).
  • Dep (Dependência): Objeto associado a cada propriedade reativa, que armazena a lista de Watchers dependentes.
  • Watcher: Representa um componente, uma propriedade computada ou watchers que dependem de dados reativos. Quando os dados mudam, o Watcher é notificado e executa a ação correspondente (por exemplo, re-renderizar o componente).

Exemplo (Vue 2):

// Implementação interna (simplificada)
function defineReactive(obj, key, val) {
  let dep = new Dep(); // Cria um Dep para a propriedade

  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      // Se houver um `Watcher` global (ao renderizar o componente)
      if (Dep.target) {
        dep.depend(); // Adiciona o `Watcher` à lista de dependências do `Dep`
      }
      return val;
    },
    set: function reactiveSetter(newVal) {
      if (newVal === val) return;
      val = newVal;
      dep.notify(); // Notifica todos os `Watcher`s dependentes
    }
  });
}

// Como isso aparece num componente
new Vue({
  data: {
    message: 'Hello' // defineReactive será aplicado a message
  },
  template: '<div>{{ message }}</div>' // Ao aceder a message, o `Watcher` deste template será adicionado ao `Dep` de message
});