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
Proxypara 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$setpara 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
});