用vue联动jq老项目

621 阅读1分钟

项目背景

    1. 平台集成了jq和vue,jq可以通过$直接调用,vue需要new出来并挂载在盒子上
    1. 地图组件是已经用jq封装好的组件,可以直接调用api
    1. 列表组件是自己通过new的vue,结合element-ui完成的

项目需求

    1. 将地图和列表联动,达到在地图上操作数据或者在列表上操作数据时,另一个组件会立即做出响应

项目实践

    1. 既然是响应式,那自然而然绕不开Object.defineProperty以及Proxy了,因为传过来的是数组, 并且在联动的过程中必然涉及到数组的增删改,那么,根据实际情况,只能选择Proxy了
    1. 在拿到数据之后,将数据改造为代理数据,在里面增加拦截功能,当数据改变时调用改变视图的函数
function deepProxy(obj, cb=()=>{console.log("操作视图")}) {
    if (typeof obj === 'object') {
        for (let key in obj) {
            if (typeof obj[key] === 'object') {
                obj[key] = deepProxy(obj[key], cb);
            }
        }
    }
    return new Proxy(obj, {
        set: function (target, key, value, receiver) {
            cb()
            console.log("key===="+key+"===value==="+value)
            return Reflect.set(target, key, value, receiver);
        },
    });
 
}

功能优化

功能我们已经完成了,但是这样的成果很明显是通过不了测试的,因为在列表中有批量的操作,而渲染地图是一件很费性能的一件事情。 所以我们需要将操作视图的函数放在数据操作完之后再去执行,个人的写法是设立一个定时器,类似于防抖的写法

let timer=null
function deepProxy(obj, cb=()=>{console.log("操作视图")}) {
    if (typeof obj === 'object') {
        for (let key in obj) {
            if (typeof obj[key] === 'object') {
                obj[key] = deepProxy(obj[key], cb);
            }
        }
    }
    return new Proxy(obj, {
        set: function (target, key, value, receiver) {
            if(timer!==null){
                clearTimeout(timer)
            }
            timer=setTimeout(() => {
               cb()
            }, 0);
            
            console.log("key===="+key+"===value==="+value)
            return Reflect.set(target, key, value, receiver);
        },
    });
 
}