如何在修改对象属性时触发回调?
How can I trigger a callback when an object attribute is modified?
如果我class喜欢:
class Myclass {
constructor(){
this.a = [];
this.sum = 0;
}
update(){
this.sum = this.a.reduce((a, b) => a + b, 0)
}
}
我实例化 class:
myClass = new Myclass();
我在 a
属性中附加了一个数字
myClass.a.push(1);
myClass.a.push(2);
如何在每次修改a
属性时调用update方法?换句话说,如何在对象属性更改时触发回调?
也许通过将对象组织为
class Myclass {
constructor(){
this.a = [];
}
get sum(){
return this.a.reduce((a, b) => a + b, 0)
}
}
如果我没记错,调用 myClass.sum
将 return a
属性下保存的数组中的总值。
添加将新项目推送到 a
数组的方法,例如:
class Myclass {
constructor(){
this.a = [];
this.sum = 0;
}
update(){
this.sum = this.a.reduce((a, b) => a + b, 0)
}
pushItem(val) {
this.a.push(val);
this.update();
}
}
myClass = new Myclass();
myClass.pushItem(1);
myClass.pushItem(2);
console.log(myClass.sum);
In other words, how can I trigger a callback when an object attribute is altered?
这是对上述问题的一般解决方案。如果您只需要 a
数组的用例特定解决方案,请忽略此。
检查 ES6 Proxies 比简单的 getters/setters get/set 拦截更强大的东西。由于你有一个嵌套的数据结构,你可能想用代理递归包装。像这样:
function wrapWithProxyCallback(obj, callback) {
return new Proxy(obj, {
get (target, key, receiver) {
const result = Reflect.get(target, key, receiver)
// wraps nested data with Proxy
if (typeof result === 'object' && result !== null) {
return wrapWithProxyCallback(result, callback)
}
return result
},
set (target, key, value, receiver) {
// calls callback on every set operation
callback(target, key, value /* and whatever else you need */)
return Reflect.set(target, key, value, receiver)
}
})
}
并像这样使用它:
const wrappedClass = wrapWithCallback(
myClass,
(target, key) => console.log(target[key])
)
// this will call the above callback
wrappedClass.a.push(1);
这有点天真,但却是一个很好的通用起点。例如,您可能想检查嵌套数据是否已被代理包装。
你想做的可能是与透明反应性很好地保持一致(不过我必须查看你的回调内容才能确定这一点。)我认为你应该查看 mobx 或@nx-js/observer-util(后者由我编写)用于生产就绪的盒装解决方案。
编辑:我的第一个示例触发了 get 操作的回调,我更正了它以触发 set 操作。
一种方法是扩展 Array
并隐藏 push
方法。
class MyArray extends Array{
constructor(ref){
super();
this.ref = ref
}
push(value){
super.push(value)
this.ref.update()
console.log("called")
}
}
class Myclass {
constructor(){
this.a = new MyArray(this);
this.sum = 0;
}
update(){
this.sum = this.a.reduce((a, b) => a + b, 0)
}
}
let myClass = new Myclass()
myClass.a.push(1);
myClass.a.push(2);
console.log(myClass.sum)
P.S:- 如果您在插入后不使用总和值,那么在每次插入时调用回调当然不是一个好主意。
如果我class喜欢:
class Myclass {
constructor(){
this.a = [];
this.sum = 0;
}
update(){
this.sum = this.a.reduce((a, b) => a + b, 0)
}
}
我实例化 class:
myClass = new Myclass();
我在 a
属性中附加了一个数字
myClass.a.push(1);
myClass.a.push(2);
如何在每次修改a
属性时调用update方法?换句话说,如何在对象属性更改时触发回调?
也许通过将对象组织为
class Myclass {
constructor(){
this.a = [];
}
get sum(){
return this.a.reduce((a, b) => a + b, 0)
}
}
如果我没记错,调用 myClass.sum
将 return a
属性下保存的数组中的总值。
添加将新项目推送到 a
数组的方法,例如:
class Myclass {
constructor(){
this.a = [];
this.sum = 0;
}
update(){
this.sum = this.a.reduce((a, b) => a + b, 0)
}
pushItem(val) {
this.a.push(val);
this.update();
}
}
myClass = new Myclass();
myClass.pushItem(1);
myClass.pushItem(2);
console.log(myClass.sum);
In other words, how can I trigger a callback when an object attribute is altered?
这是对上述问题的一般解决方案。如果您只需要 a
数组的用例特定解决方案,请忽略此。
检查 ES6 Proxies 比简单的 getters/setters get/set 拦截更强大的东西。由于你有一个嵌套的数据结构,你可能想用代理递归包装。像这样:
function wrapWithProxyCallback(obj, callback) {
return new Proxy(obj, {
get (target, key, receiver) {
const result = Reflect.get(target, key, receiver)
// wraps nested data with Proxy
if (typeof result === 'object' && result !== null) {
return wrapWithProxyCallback(result, callback)
}
return result
},
set (target, key, value, receiver) {
// calls callback on every set operation
callback(target, key, value /* and whatever else you need */)
return Reflect.set(target, key, value, receiver)
}
})
}
并像这样使用它:
const wrappedClass = wrapWithCallback(
myClass,
(target, key) => console.log(target[key])
)
// this will call the above callback
wrappedClass.a.push(1);
这有点天真,但却是一个很好的通用起点。例如,您可能想检查嵌套数据是否已被代理包装。
你想做的可能是与透明反应性很好地保持一致(不过我必须查看你的回调内容才能确定这一点。)我认为你应该查看 mobx 或@nx-js/observer-util(后者由我编写)用于生产就绪的盒装解决方案。
编辑:我的第一个示例触发了 get 操作的回调,我更正了它以触发 set 操作。
一种方法是扩展 Array
并隐藏 push
方法。
class MyArray extends Array{
constructor(ref){
super();
this.ref = ref
}
push(value){
super.push(value)
this.ref.update()
console.log("called")
}
}
class Myclass {
constructor(){
this.a = new MyArray(this);
this.sum = 0;
}
update(){
this.sum = this.a.reduce((a, b) => a + b, 0)
}
}
let myClass = new Myclass()
myClass.a.push(1);
myClass.a.push(2);
console.log(myClass.sum)
P.S:- 如果您在插入后不使用总和值,那么在每次插入时调用回调当然不是一个好主意。