Pular para o conteúdo principal

[Hard] Ligação Bidirecional de Dados

1. Please explain the underlying principle of how Vue2 and Vue3 each implement two-way binding

Explique o princípio subjacente de como Vue2 e Vue3 implementam a ligação bidirecional

Para entender a ligação bidirecional do Vue, é necessário primeiro compreender o mecanismo do sistema reativo é as diferenças de implementação entre Vue2 e Vue3.

Implementação do Vue2

O Vue2 usa Object.defineProperty para implementar a ligação bidirecional. Este método pode transformar propriedades de um objeto em getter e setter, permitindo monitorar mudanças nas propriedades.

1. Data Hijacking (Sequestro de Dados)

No Vue2, quando um objeto de dados de um componente é criado, o Vue percorre todas as propriedades do objeto e usa Object.defineProperty para convertê-las em getter e setter, permitindo rastrear leituras e modificações dos dados.

2. Dependency Collection (Coleta de Dependências)

Sempre que a função de renderização do componente é executada, ela lê propriedades do data, acionando o getter. O Vue registra essas dependências para notificar os componentes que dependem desses dados quando houver mudanças.

3. Dispatching Updates (Despacho de Atualizações)

Quando os dados são modificados, o setter é acionado, é o Vue notifica todos os componentes que dependem desses dados para re-executar a função de renderização e atualizar o DOM.

Exemplo de Código Vue2

function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
console.log(`get ${key}: ${val}`);
return val;
},
set: function reactiveSetter(newVal) {
console.log(`set ${key}: ${newVal}`);
val = newVal;
},
});
}

const data = { name: 'Pitt' };
defineReactive(data, 'name', data.name);

console.log(data.name); // Aciona getter, imprime "get name: Pitt"
data.name = 'Vue2 Reactivity'; // Aciona setter, imprime "set name: Vue2 Reactivity"

Limitações do Vue2

  • Não detecta adição ou remoção de propriedades de objetos: Necessita usar Vue.set() ou Vue.delete()
  • Não detecta mudanças por índice em arrays: Necessita usar métodos de array do Vue (como push, pop, etc.)
  • Problema de performance: Precisa percorrer recursivamente todas as propriedades

Implementação do Vue3

O Vue3 introduziu o Proxy do ES6, que pode envolver um objeto em um proxy e monitorar mudanças nas propriedades com performance otimizada.

1. Data Hijacking com Proxy

O Vue3 usa new Proxy para criar um proxy dos dados, em vez de definir getter e setter individualmente para cada propriedade, permitindo rastrear mudanças de forma mais granular e interceptar mais tipos de operações.

2. Rastreamento de Dependências Mais Eficiente

Com Proxy, o Vue3 rastreia dependências de forma mais eficiente, pois não precisa pré-definir getter/setter, é o Proxy pode interceptar até 13 tipos de operações (como get, set, has, deleteProperty, etc.).

3. Re-renderização Minimizada Automática

Quando os dados mudam, o Vue3 pode determinar com mais precisão qual parte da UI precisa ser atualizada.

Exemplo de Código Vue3

function reactive(target) {
const handler = {
get(target, key, receiver) {
const result = Reflect.get(target, key, receiver);
console.log(`Obtendo ${key}: ${result}`);
return result;
},
set(target, key, value, receiver) {
const success = Reflect.set(target, key, value, receiver);
console.log(`Definindo ${key}: ${value}`);
return success;
},
};

return new Proxy(target, handler);
}

const data = reactive({ name: 'Vue 3' });

console.log(data.name); // Aciona get do Proxy
data.name = 'Vue 3 Reactivity'; // Aciona set do Proxy

Tabela Comparativa Vue2 vs Vue3

CaracterísticaVue2Vue3
ImplementaçãoObject.definePropertyProxy
Detectar novas propriedadesNecessita Vue.set()Suporte nativo
Detectar exclusão de propriedadesNecessita Vue.delete()Suporte nativo
Detectar índice de arrayNecessita métodos específicosSuporte nativo
PerformancePercorre recursivamente todas as propriedadesProcessamento lazy, melhor performance
Suporte a navegadoresIE9+Não suporta IE11

Conclusão

O Vue2 usa Object.defineProperty para implementar a ligação bidirecional, mas este método tem certas limitações. O Vue3 introduziu o Proxy do ES6, fornecendo um sistema reativo mais poderoso e flexível, com melhor performance.

2. Why does Vue3 use Proxy instead of Object.defineProperty?

Por que o Vue3 usa Proxy em vez de Object.defineProperty?

Principais Razões

1. Capacidade de Interceptação Mais Poderosa

Proxy pode interceptar até 13 tipos de operações, enquanto Object.defineProperty só pode interceptar leitura e escrita de propriedades.

2. Suporte Nativo a Monitoramento de Índice de Array

// Vue2 não detecta
const arr = [1, 2, 3];
arr[0] = 10; // Não aciona atualização

// Vue3 detecta
const arr = reactive([1, 2, 3]);
arr[0] = 10; // Aciona atualização

3. Suporte Nativo a Adição/Exclusão Dinâmica de Propriedades

// Vue2 precisa tratamento especial
Vue.set(obj, 'newKey', 'value');

// Vue3 suporte nativo
const obj = reactive({});
obj.newKey = 'value'; // Aciona atualização
delete obj.newKey; // Também aciona atualização

4. Melhor Performance

// Vue2: precisa percorrer recursivamente todas as propriedades
function observe(obj) {
Object.keys(obj).forEach(key => {
defineReactive(obj, key, obj[key]);
if (typeof obj[key] === 'object') {
observe(obj[key]);
}
});
}

// Vue3: processamento lazy, proxy apenas quando acessado
function reactive(obj) {
return new Proxy(obj, handler); // Sem recursão necessária
}

Por que o Vue2 Não Usou Proxy?

Principalmente por compatibilidade de navegadores: quando o Vue2 foi lançado (2016), Proxy ainda não era amplamente suportado e não pode ser polyfilled. O Vue3 abandonou o suporte ao IE11, permitindo o uso de Proxy.

Resumo

O Vue3 usa Proxy para: 1) Suporte reativo mais completo; 2) Melhor performance; 3) Código mais simples; 4) Melhor experiência de desenvolvimento. O único custo é abandonar o suporte a navegadores antigos (IE11).

Reference