Langsung ke konten utama

[Hard] ๐Ÿ“„ Two-way Data Binding

1. Jelaskan prinsip dasar cara Vue2 dan Vue3 masing-masing mengimplementasikan two-way bindingโ€‹

Jelaskan mekanisme dasar two-way binding di Vue2 dan Vue3.

Untuk memahami two-way binding Vue, Anda perlu memahami cara kerja sistem reaktivitas dan bagaimana Vue2 serta Vue3 mengimplementasikannya secara berbeda.

Implementasi Vue2โ€‹

Vue2 menggunakan Object.defineProperty untuk mengimplementasikan reaktivitas. Ia membungkus properti objek dengan getter dan setter, sehingga pembacaan/penulisan dapat dilacak.

1. Data hijacking (pembajakan data)โ€‹

Saat data component diinisialisasi di Vue2, Vue menelusuri setiap properti dan mengubahnya menjadi getter/setter melalui Object.defineProperty, sehingga pembacaan dan penulisan dapat diamati.

2. Pengumpulan dependensiโ€‹

Saat fungsi render dieksekusi dan membaca properti reaktif, getter berjalan. Vue mencatat dependensi sehingga component yang terdampak dapat diberitahu nanti.

3. Mengirimkan pembaruanโ€‹

Saat data berubah, setter berjalan. Vue memberitahu watcher/component yang bergantung dan memicu render ulang untuk memperbarui DOM.

Contoh 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); // memicu getter
data.name = 'Vue2 Reactivity'; // memicu setter

Keterbatasan Vue2โ€‹

Object.defineProperty memiliki beberapa keterbatasan:

  • Tidak dapat mendeteksi penambahan/penghapusan properti tanpa Vue.set() / Vue.delete()
  • Tidak dapat mendeteksi mutasi indeks array secara langsung secara andal tanpa method array yang di-patch
  • Overhead performa dari penelusuran mendalam dan definisi getter/setter di awal

Implementasi Vue3โ€‹

Vue3 menggunakan ES6 Proxy, yang memberikan kemampuan intersepsi yang lebih luas dan karakteristik performa yang lebih baik.

1. Data hijacking berbasis Proxyโ€‹

Vue3 membungkus seluruh objek dengan new Proxy alih-alih mendefinisikan getter/setter per key. Ini memungkinkan intersepsi lebih banyak operasi, termasuk penambahan/penghapusan properti.

2. Pelacakan dependensi yang lebih efisienโ€‹

Vue3 tidak lagi membutuhkan definisi getter/setter di awal untuk setiap properti. Trap Proxy dapat menangani operasi secara dinamis (misalnya get, set, has, deleteProperty, dll.).

3. Pemicuan pembaruan yang lebih presisiโ€‹

Vue3 dapat melacak dependensi dengan lebih presisi dan mengurangi render ulang yang tidak perlu.

Contoh Vue3โ€‹

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

return new Proxy(target, handler);
}

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

console.log(data.name);
data.name = 'Vue 3 Reactivity';
console.log(data.name);

Perbandingan Vue2 vs Vue3โ€‹

FiturVue2Vue3
Mekanisme intiObject.definePropertyProxy
Mendeteksi properti baruMembutuhkan Vue.set()Dukungan native
Mendeteksi penghapusan propertiMembutuhkan Vue.delete()Dukungan native
Mendeteksi penugasan indeks arrayTerbatasDukungan native
PerformaPenelusuran mendalam di awalLazy + lebih efisien
Dukungan browserIE9+Tidak mendukung IE11

Kesimpulanโ€‹

Vue2 menggunakan Object.defineProperty, yang berfungsi tetapi memiliki keterbatasan yang diketahui. Vue3 menggunakan Proxy, memberikan sistem reaktivitas yang lebih lengkap dan fleksibel dengan performa yang lebih baik.

2. Mengapa Vue3 menggunakan Proxy alih-alih Object.defineProperty?โ€‹

Mengapa Vue3 memilih Proxy daripada Object.defineProperty?

Alasan utamaโ€‹

1. Kemampuan intersepsi yang lebih kuatโ€‹

Proxy dapat mengintersepsi banyak operasi, sedangkan Object.defineProperty hanya mencakup get/set properti.

// Operasi yang dapat diintersepsi Proxy
const handler = {
get() {},
set() {},
has() {},
deleteProperty() {},
ownKeys() {},
getOwnPropertyDescriptor() {},
defineProperty() {},
preventExtensions() {},
getPrototypeOf() {},
isExtensible() {},
setPrototypeOf() {},
apply() {},
construct() {},
};

2. Pelacakan indeks array secara nativeโ€‹

// Keterbatasan Vue2
const arr = [1, 2, 3];
arr[0] = 10; // sering tidak terlacak di model defineProperty gaya Vue2

// Vue3
const arr2 = reactive([1, 2, 3]);
arr2[0] = 10; // terlacak

3. Dukungan native untuk penambahan/penghapusan properti dinamisโ€‹

// Vue2 membutuhkan API khusus
Vue.set(obj, 'newKey', 'value');

// Vue3 native
const obj = reactive({});
obj.newKey = 'value';
delete obj.newKey;

4. Model performa yang lebih baikโ€‹

// Vue2: penelusuran mendalam + defineReactive untuk setiap key
function observe(obj) {
Object.keys(obj).forEach((key) => {
defineReactive(obj, key, obj[key]);
if (typeof obj[key] === 'object') {
observe(obj[key]);
}
});
}

// Vue3: pembungkus proxy
function reactive(obj) {
return new Proxy(obj, handler);
}

5. Implementasi internal yang lebih sederhanaโ€‹

Inti reaktivitas Vue3 lebih bersih dan lebih mudah dipelihara.

Mengapa Vue2 tidak menggunakan Proxyโ€‹

Terutama kompatibilitas browser:

  • Vue2 (dirilis tahun 2016) membutuhkan dukungan luas termasuk IE
  • Proxy tidak dapat di-polyfill secara penuh
  • Vue3 menghentikan dukungan IE11, sehingga Proxy menjadi layak

Perbandingan praktisโ€‹

// ===== Keterbatasan Vue2 =====
const vm = new Vue({
data: {
obj: { a: 1 },
arr: [1, 2, 3],
},
});

// tidak andal reaktif di Vue2 tanpa API khusus
vm.obj.b = 2;
delete vm.obj.a;
vm.arr[0] = 10;
vm.arr.length = 0;

// Workaround Vue2
Vue.set(vm.obj, 'b', 2);
Vue.delete(vm.obj, 'a');
vm.arr.splice(0, 1, 10);

// ===== Dukungan native Vue3 =====
const state = reactive({
obj: { a: 1 },
arr: [1, 2, 3],
});

state.obj.b = 2;
delete state.obj.a;
state.arr[0] = 10;
state.arr.length = 0;

Ringkasanโ€‹

Vue3 menggunakan Proxy untuk:

  1. Memberikan cakupan reaktivitas yang lengkap (perubahan tambah/hapus/indeks)
  2. Meningkatkan performa (lebih sedikit penelusuran di awal)
  3. Menyederhanakan implementasi
  4. Meningkatkan pengalaman developer (lebih sedikit API khusus)

Tradeoff: tidak mendukung IE11 legacy, yang dapat diterima untuk target web modern.

Referensiโ€‹