在Javascript中观察数组的变化是相对简单的。
我使用的一种方法是这样的:
// subscribe to add, update, delete, and splice changes
Array.observe(viewHelpFiles, function(changes) {
// handle changes... in this case, we'll just log them
changes.forEach(function(change) {
console.log(Object.keys(change).reduce(function(p, c) {
if (c !== "object" && c in change) {
p.push(c + ": " + JSON.stringify(change[c]));
}
return p;
}, []).join(", "));
});
});
但是,我最近读到Array.observe
已被弃用,我们应该改用代理对象。
我们如何检测代理对象数组中的更改?我找不到任何例子,有人有兴趣详细说明吗?
从我从 MDN 页面读取的内容来看,您可以创建一个通用处理程序,您可以在其中处理对任何对象的所有更改。
从某种意义上说,你写了一个拦截器,每次你从数组中获取值或设置一个值时,它都会进行干预。然后,您可以编写自己的逻辑来跟踪更改。
var arrayChangeHandler = {
get: function(target, property) {
console.log('getting ' + property + ' for ' + target);
// property is index in this case
return target[property];
},
set: function(target, property, value, receiver) {
console.log('setting ' + property + ' for ' + target + ' with value ' + value);
target[property] = value;
// you have to return true to accept the changes
return true;
}
};
var originalArray = [];
var proxyToArray = new Proxy( originalArray, arrayChangeHandler );
proxyToArray.push('Test');
console.log(proxyToArray[0]);
// pushing to the original array won't go through the proxy methods
originalArray.push('test2');
// the will however contain the same data,
// as the items get added to the referenced array
console.log('Both proxy and original array have the same content? '
+ (proxyToArray.join(',') === originalArray.join(',')));
// expect false here, as strict equality is incorrect
console.log('They strict equal to eachother? ' + (proxyToArray === originalArray));
然后输出:
getting push for
getting length for
setting 0 for with value Test
setting length for Test with value 1
getting 0 for Test
Test
代理的警告是,对象上定义的所有内容都将被截获,这在使用push
方法时可以观察到。
发生突变,并且代理不会捕获对原始对象所做的更改。
你可以做这样的事情
new Proxy([], {
get(target, prop) {
const val = target[prop];
if (typeof val === 'function') {
if (['push', 'unshift'].includes(prop)) {
return function (el) {
console.log('this is a array modification');
return Array.prototype[prop].apply(target, arguments);
}
}
if (['pop'].includes(prop)) {
return function () {
const el = Array.prototype[prop].apply(target, arguments);
console.log('this is a array modification');
return el;
}
}
return val.bind(target);
}
return val;
}
});