Vue 要做 一个 对象{} 的 修改后的 恢复功能,请教

要做 一个 对象{} 的 修改后的 恢复功能,

实现很简单。弄一个数组 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>
您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!
PS:问答VIP年卡 【限时加赠:IT技术图书免费领】,了解详情>>> https://vip.csdn.net/askvip?utm_source=1146287632