vue响应式原理
普通方式对对象的操作无法实现响应式
//#region
// let name='bwf'
// let age=18
// let obj1={
// name,
// age
// }
//#endregion
vue2响应式原理
存在的问题:
1.增加和删除对象的属性时无法实现响应式,如果需要增加对象属性可以调用set方法,如下
this.$set(this.user,'sex','女')
Vue.set(this.user,'sex','女')
注意:对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property
- 通过修改数组的索引和length属性无法实现对数组的更新,解决方法如下:
Vue.set(vm.items, indexOfItem, newValue)
m.$set(vm.items, indexOfItem, newValue)
//或者
vm.items.splice(indexOfItem, 1, newValue)
vue2响应式原理的简单实现
let data = {
name: 'bwf',
age: 18
}
// vue2响应式的简单实现,创建了一个Observer构造函数,用于把传过来的数据加工成响应式的
function Observer(obj) {
Object.keys(obj).forEach(key => {
//把obj上的属性复制到this,即构造函数的实例身上
return Object.defineProperty(this, [key], {
get() {
return obj[key]
},
set(value) {
obj[key] = value
console.log(`有人修改了${key}属性,我要去更新模板了。。。`)
}
})
})
}
const obs = new Observer(data);
const vm = {};
vm._data = data = obs;
console.log('obs', obs);
vue3响应式原理
借助了es6中的Reflect对象与Proxy对象
let obj1 = {
name: 'bwf',
age: 18
}
let obj2 = new Proxy(obj1, {
// target代理的目标对象,这里指obj1,propKey目标对象的key值
get(target, propKey) {
// console.log(target, propKey)
// return target[propKey]
return Reflect.get(target, target[propKey])
},
// 当修改或新增代理对象的属性时set方法会调用
set(target, propKey, value) {
console.log(`有人修改了${target}的${propKey}属性`)
console.log(target, propKey, value)
// target[propKey] = value
Reflect.set(target, propKey, value)
},
// 当删除对象的某个属性时deleteProperty方法会调用
deleteProperty(target, propKey) {
console.log(`有人删除了${target}属性`)
// delete target[propKey]
Reflect.deleteProperty(target, propKey)
}
})
Object.defineProperty 与Reflect.defineProperty的比较
详细请看es6官方文档 es6.ruanyifeng.com/#docs/refle…
Object.defineProperty 定义对象属性若同名会报错,影响后面代码的执行,若不想整个页面报错,需要放在try...catch中
//#region
let num1 = {
a: 1
}
let num2 = {}
try {
Object.defineProperty(num2, 'a', {
get() {
return 100
},
set(value) {
num1.a = 200
}
})
Object.defineProperty(num2, 'a', {
get() {
return 300
},
set(value) {
num1.a = 200
}
})
} catch (error) {
console.log(error)
}
console.log('hah')
//#endregion
- Reflect.defineProperty定义对象属性若同名不会报错,后定义的不会生效
- Reflect.defineProperty可以接受一个返回值,为true/false
//#region
let num1 = {
a: 1
}
let num2 = {}
let res1 = Reflect.defineProperty(num2, 'a', {
get() {
return 100
},
set(value) {
num1.a = 200
}
})
console.log(res1)
let res2 = Reflect.defineProperty(num2, 'a', {
get() {
return 300
},
set(value) {
num1.a = 200
}
})
console.log(res2)
if (res1) {
console.log('执行成功的代码')
} else {
console.log('执行失败的代码')
}
console.log('hah')
//#endregion
so,大型框架中一般使用Reflect来操作对象。