js深度监听对象的变化
众说周知,对对象进行属性的监听要使用 Object.defineProperty
这个方法,如果不知道请先去了解一下。
- 我们使用
Object.defineProperty
监听一层对象时是非常简单的,但难在如何监听更深的对象,比如对象中有个属性值是对象,对象中又有个属性值又是对象,这种监听就有一点难度了,咱们废话不多说直接上代码
下面这个函数就能实现对对象的深度监听,方法中有三个参数
object
是一个你需要提前准备的空对象,它用来接收要监听的对象value
是你要监听的对象,对象的值最后会放在 你传给object
的对象fun
是一个回调当监听对象中数据发生改变时就会调用
let DataBroker = function (object, value, fun) {
function ArrayBroker(arr, fun) {
let newPrototype = Object.create(Array.prototype);
let methods = ["push", "pop", "shift", "unshift", "reverse", "sort", "splice"];
methods.forEach(method => {
newPrototype[method] = function (...args) {
//! 关键部分 我们使用延时定时器将函数调用由同步变为异步操作
//! 这步是为了让对数组的的操作先执行,在执行函数的调用
setTimeout(function () {
fun();
}, 0);
return Array.prototype[method].call(this, ...args);
};
});
arr.__proto__ = newPrototype;
//判断数组中是否有对象和数组如果有进行get set和数组监听
for (let i = 0; i < arr.length; i++) {
if (arr[i] instanceof Array) {
ArrayBroker(arr[i], fun);
} else if (arr[i] instanceof Object) {
let temp = arr[i];
arr[i] = new Object();
DataBroker(arr[i], temp, fun);
}
}
};
for (let i in value) {
if (value[i] instanceof Array) {
//! 防止对原数组的更改
object[i] = [...value[i]];
ArrayBroker(object[i], fun);
} else if (value[i] instanceof Object) {
let obj = new Object();
object[i] = obj;
DataBroker(object[i], value[i], fun);
} else {
Object.defineProperty(object, i, {
enumerable: true,
get() {
return value[i];
},
set(val) {
value[i] = val;
fun();
}
});
};
};
fun();
};
示例
//定义一个空对象
let _data = {};
DataBroker(_data, {
//需要监听的对象
name: '张三',
adg: 30,
user: {
name: '李四',
adg: 20,
arr:['0','1','2']
}
}, function () {
//回调函数
console.log('数据发送改变');
});
修改对象中是数据,监听到数据的改变,调用回调函数
数据中如果有数组的话只能使用以下API操作数组才能实现监听
push(), pop(), shift(), unshift(), reverse(), sort(), splice()