单层监听
只监听对象单层的属性变化。目前没有对map、set等类型的数据做监听,后续慢慢更新。
//监听对象属性值是否发生改变,对象属性数量是否变化
//参数: object 要代理的对象名称,
// callback: {
// //getter 对象访问属性时会出发,如果此方法没有返回值,则返回对象属性本生的值。
// onGet: function(object, property) {
// //object:代理后的对象,
// //property:访问的属性。
// },
// //setter 对象属性赋值时会触发方法。
// onSet: function(object, property, value) {
// //object:代理后的对象,
// //property:访问的属性。
// //value:设置的值
// },
// onProtertyNumChage: function(object) {
// //object:代理后的对象,
// //property:访问的属性。
// }
// }
class ObjectListener {
constructor(object, callback, config) {
this.object = object
//声明自定义方法
this.callback = {
onGet: function (object, property) {},
onSet: function (object, property, value) {},
onProtertyNumChage: function (object) {}
}
//默认值
this.callback.onGet = callback.onGet || this.callback.onGet
this.callback.onSet = callback.onSet || this.callback.onSet
this.callback.onProtertyNumChage = callback.onProtertyNumChage || this.callback.onProtertyNumChage
//声明触发配置
this.config = {
enableOnSetWhenKyesChange: false,
//添加属性时不再触发onSet
enableOnProtertyNumChage: true
//添加属性时触发OnProtertyNumChage,如果此项为False,则只会触发onSet并且覆盖enableOnSetWhenKyesChange配置
}
if (config) {
this.config.enableOnSetWhenKyesChange = Reflect.has(config, "enableOnSetWhenKyesChange") ? config.enableOnSetWhenKyesChange : this.config.enableOnSetWhenKyesChange
this.config.enableOnProtertyNumChage = Reflect.has(config, "enableOnProtertyNumChage") ? config.enableOnProtertyNumChage : this.config.enableOnProtertyNumChage
}
this.Proxys = new Proxy(object, this.iinterceptor)
this.objKeys = Object.keys(this.object).length //用于判断对象属性数量是否发生变化
Object.defineProperty(this, "num", {
set(value) {
this.objKeys = value
this.callback.onProtertyNumChage(this.Proxys)
},
get() {
return this.objKeys
}
})
return this.Proxys
}
iinterceptor = {
//将父级对象传值到此对象
_parent_: this,
set: function (object, property, value) {
object[property] = value
//监听对象属性数量是否发生变化
if (Object.keys(object).length !== this._parent_.num && this._parent_.config.enableOnProtertyNumChage) {
this._parent_.num = Object.keys(object).length
if (!this._parent_.config.enableOnSetWhenKyesChange) return value
}
//如果onSet没有返回值,则对象赋值值为vlaue
object[property] = this._parent_.callback.onSet(this._parent_.Proxys, property, value) || value
return value
},
get: function (object, property) {
if (property === "num") {
return this._parent_.objKeys
}
return this._parent_.callback?.onGet(object, property) || object[property]
}
}
}
调用
// object === objectListener 都是代理后的对象
let objectListener= new ObjectListener(targetObject, {
onGet: function (object, property) {
console.log('onGet')
},
onSet: function (object, property, value) {
console.log('onSet')
},
onProtertyNumChage: function (object) {
console.log("onProtertyNumChage");
}
}, {
enableOnSetWhenKyesChange: false,//添加属性时不再触发onSet
enableOnProtertyNumChage: true//添加属性时触发OnProtertyNumChage,如果此项为False,则只会触发onSet并且覆盖enableOnSetWhenKyesChange配置
})
深度监听
在单层监听的基础上,做递归操作。便利对象,如果属性为对象,则使用代理并且把代理后的对象赋值到当前对象的相应属性下。
class ObjectListenerDeep {
constructor(object, callback) {
this.deepRecording = null
this.object = object
//声明自定义方法
this.callback = {
onGet: function (object, property) {},
onSet: function (object, property, value) {},
onProtertyNumChage: function (object) {}
}
//默认值
this.callback.onGet = callback.onGet || this.callback.onGet
this.callback.onSet = callback.onSet || this.callback.onSet
this.callback.onProtertyNumChage = callback.onProtertyNumChage || this.callback.onProtertyNumChage
//声明触发配置
this.config = {
enableOnSetWhenKyesChange: false,
//添加属性时不再触发onSet
enableOnProtertyNumChage: true
//添加属性时触发OnProtertyNumChage,如果此项为False,则只会触发onSet并且覆盖enableOnSetWhenKyesChange配置
//深度监听时,增加和删除属性会出现判断错误,默认为flase
//所有的新增和修改都会触发set,因此不再提供可配置项
}
if (config) {
this.config.enableOnSetWhenKyesChange = Reflect.has(config, "enableOnSetWhenKyesChange") ? config.enableOnSetWhenKyesChange : this.config.enableOnSetWhenKyesChange
this.config.enableOnProtertyNumChage = Reflect.has(config, "enableOnProtertyNumChage") ? config.enableOnProtertyNumChage : this.config.enableOnProtertyNumChage
}
this.objectEach()
return this.deepRecording
}
objectEach() {
let _this = this
function traverse(object) {
for (const key in object) {
if (Object.hasOwnProperty.call(object, key)) {
const element = object[key]
if (typeof element === "object" && !Array.isArray(element)) {
traverse(element)
object[key] = _this.newObjectListener(element)
}
}
}
}
this.deepRecording = _this.newObjectListener(_this.object)
traverse(_this.object)
// this.object
}
newObjectListener(object) {
let _this = this
return new ObjectListener(
object,
{
onGet: _this.callback.onGet,
onSet: _this.callback.onSet,
onProtertyNumChage: _this.callback.onProtertyNumChage
},
{
enableOnSetWhenKyesChange: _this.config.enableOnSetWhenKyesChange,
enableOnProtertyNumChage: _this.config.enableOnProtertyNumChage
}
)
}
}
调用
let saveDataListener2 = new ObjectListenerDeep(targetObject, {
onGet: function (object, property) {
//console.log('get', property, object)
},
onSet: function (object, property, value) {
//console.log('set', property, value, object)
}
})
代码还很简陋,仅仅作为一个学习记录。
发现一个问题,在封装的回调中不能多次赋值否则会循环调用导致爆栈