模仿VUE2實現響應式
Vue2: 通過Object.defineProperty()來實現
1. 代碼
// 模仿vue2實現響應式
let person = {
name: '張三',
age: 20
}
let person_vue2 = {}
Object.defineProperty(person_vue2, 'name', {
configurable: true,
get() {
console.log('讀取name屬性');
return person.name
},
set(value) {
console.log('修改name屬性');
person.name = value
}
})
Object.defineProperty(person_vue2, 'age', {
get() {
console.log('讀取age屬性');
return person.age
},
set(value) {
console.log('修改age屬性');
person.age = value
}
})
2. 一些操作
- 讀、改 操作可以響應式
- 給person_vue2添加hobby屬性,可以添加成功,但是set監聽不到,沒有響應式。對應hobby屬性沒有get和set方法。
3.弊端
- 新增屬性、刪除屬性,界面不會更新
- 直接通過下標修改數組,界面不會自動更新
- 要一個屬性一個屬性改(就算使用循環也還是很麻煩)
4. 解決
- 對象
this.$set(object,'propName',value)
Vue.set(object,'propName',value)
this.$delete(object, 'propName')
Vue.delete(object, 'propName')
- 數組
this.$set(array,index,value)
this.array.splice()
Vue3: 通過proxy實現
1.初步實現
let person = {
name: '張三',
age: 20
}
// 模仿vue3實現響應式
let person_vue3 = new Proxy(person, {})
這時候查看一下增刪改查操作:
- 查看person_vue3,是一個proxy對象
- 給person_vue3添加hobby屬性,對應person也有了
- 修改和刪除屬性類似
2.捕獲操作,實現響應式
let person = {
name: '張三',
age: 20
}
// 模仿vue3實現響應式
let person_vue3 = new Proxy(person, {
get(target, propName) {
console.log(`讀取person_vue3的${propName}屬性`);
// propName是變量,不可以使用target.propName來讀取屬性
return target[propName]
},
set(target, propName, value) {
console.log(`修改person_vue3的${propName}屬性`);
target[propName] = value
},
deleteProperty(target, propName) {
console.log(`刪除person_vue3的${propName}屬性`);
return target[propName]
})
3. Reflect
使用ReflectReflect的MDN鏈接
let person = {
name: '張三',
age: 20
}
// 模仿vue3實現響應式
let person_vue3 = new Proxy(person, {
get(target, propName) {
console.log(`讀取person_vue3的${propName}屬性`);
// propName是變量,不可以使用target.propName來讀取屬性
// return target[propName]
return Reflect.get(target, propName)
},
set(target, propName, value) {
console.log(`修改person_vue3的${propName}屬性`);
// target[propName] = value
Reflect.set(target, propName, value)
},
deleteProperty(target, propName) {
console.log(`刪除person_vue3的${propName}屬性`);
// return target[propName]
return Reflect.deleteProperty(target, propName)
}
})