通过Object.defineProperty来实现响应式
const obj = {
name: 'zxt',
age: '18',
sex: 'nan',
son: {
name: 'zzz',
sex: 'nan'
},
arr: [1, 2, 3],
}
/**
* 监听对象每一项的读取与写入
* @param {*} obj 对象
* @param {*} prop 属性
* @param {*} value 值
*/
function defineReactive(obj, prop, value) {
if (typeof value === "object") {
forIn(obj[prop]);
}
Object.defineProperty(obj, prop, {
get() {
console.log('读');
return value;
},
set(nowValue) {
console.log('写');
value = nowValue;
render();
}
})
}
/**
* 迭代对象的每一个属性
* @param {*} obj
*/
function forIn(obj) {
/**
* 当为数组是,为其绑定数组异变方法
*/
if (Array.isArray(obj)) {
obj.__proto__ = arrMethods;
return;
}
if (typeof obj == 'object') {
for (const key in obj) {
defineReactive(obj, key, obj[key]);
};
}
}
function render() {
console.log('页面渲染啦');
}
/**
* 数据的变异方法
*/
let arrProto = Array.prototype;
let arrMethods = Object.create(arrProto);
['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach((ele) => {
arrMethods[ele] = function () {
arrProto[ele].call(this, ...arguments)
render();
}
})
/**
* $set
*/
function $set(who, revise, value) {
if (Array.isArray(who)) {
who.splice(revise, 1, value);
return value;
}
defineReactive(who,revise,value)
return value;
// render();
}
/**
* $delete
*/
function $delete(obj ,target){
if(Array.isArray(obj)){
obj.splice(target,0);
return;
}
delete obj[target] ;
return;
}
forIn(obj);
obj.son.name = 123;
利用Object.defineProperty实现响应式的劣势
- 天生就需要进行递归
- 监听不到数组不存在的索引的改变
- 监听不到数组长度的改变
- 监听不到对象的增删