要做 一个 对象{} 的 修改后的 恢复功能,
实现很简单。弄一个数组 arr
每次修改前深拷贝一个 对象, arr.push 一个进去。 恢复时依次取出就行。
但是我看了一下 wps 或 office 的恢复功能,所有操作步骤,可以一直恢复出来
这样,我的想法就太简单了。 当 对象{} 大的时候,会不会很占资源?。
其实有时 仅是修改了 对象 一个小局部。只要恢复这个局部就行。
如果是备份局部,我现的想法如下:
arr = 备份数组
function(){
obj 是要 修改的对象
a = obj 1 先备份一个 整体
b = obj 2 执行修改后的 整体
这里时进行 obj 1 与 obj 2 的 比对
c= 比对 a 和b,把不同的部份
把 c 加入 备份数组。arr.pusth(c)
恢复时,就把 c 再和 当前{} 比对,一个一个改回去
}
这里请教,一般你们遇到这种需求,会怎么做 ,有什么好方法
用Proxy监控对象属性更改,arr数组直接压入被修改的操作,比如键名称和原始值。简单示例如下
<script>
var ops = [];//操作历史
var obj = {old:111};
var proxy = new Proxy(obj, {
set: function (target, key, value, receiver) {
let op = { key};
if (target[key] === undefined) {//不存在这个属性则标记操作未新增
op.op = 'add';
} else {
op.op = 'update';
op.value = target[key];//存储旧值
}
ops.push(op);
return Reflect.set(target, key, value, receiver)
},
deleteProperty: function (target, key) {
let op = { key, value:target[key], op: 'delete' };
ops.push(op);
delete target[key];//操作原对象
return true;
}
});
//设置内容,操作proxy对象
delete proxy.old;
console.log(JSON.stringify(obj))
console.log(JSON.stringify(ops))
console.log('\n\n')
proxy.prop1 = 'prop1value'
console.log(JSON.stringify(obj))
console.log(JSON.stringify(ops))
console.log('\n\n')
proxy.prop1 = 'prop1-new-value'
console.log(JSON.stringify(obj))
console.log(JSON.stringify(ops))
console.log('\n\n')
//还原操作,直接操作obj对象,而不是proxy
let op
while (op = ops.pop()) {
if (op.op == 'update') {//修改则还原原旧值
obj[op.key] = op.value;//还原原来的值
}
else if (op.op == "add") {//新增,反向操作则是删除
console.log(op.key)
delete obj[op.key];
}
else if (op.op == 'delete') {//删除操作补回属性
obj[op.key] = op.value;
}
console.log(JSON.stringify(obj))
console.log(JSON.stringify(ops))
console.log('\n\n')
}
</script>
下面是 Proxy 支持的拦截操作一览,一共 13 种。
get(target, propKey, receiver):拦截对象属性的读取,比如proxy.foo和proxy['foo']。
set(target, propKey, value, receiver):拦截对象属性的设置,比如proxy.foo = v或proxy['foo'] = v,返回一个布尔值。
has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值。
deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值。
ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。
preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个布尔值。
getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象。
isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值。
setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。
construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="add">添加</button>
<button id="laststep">上一步</button>
<button id="revocation">撤销</button>
<div id="box"></div>
<script>
let add = document.getElementById("add");
let laststep = document.getElementById("laststep");
let revocation = document.getElementById("revocation");
let box = document.getElementById("box");
let arr = [], arrList = [], indexs = -1;
add.onclick = function () {
arr.push({
name: 'add',
index: arr.length
});
indexs++
arrList.push(JSON.parse(JSON.stringify(arr)))
console.log(arrList, arrList[indexs], '===', indexs)
boxcontent()
}
laststep.onclick = function () {
indexs--;
boxcontent()
}
revocation.onclick = function () {
indexs = -1;
boxcontent()
}
function boxcontent() {
if (indexs == -1) {
box.innerHTML = '暂无数据'
} else {
let str = "";
arrList[indexs].forEach((item, index) => {
str += `<span>${item.name}===${item.index}</span>`
})
box.innerHTML = str;
}
}
</script>
</body>
</html>
您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!