项目背景
-
- 平台集成了jq和vue,jq可以通过$直接调用,vue需要new出来并挂载在盒子上
-
- 地图组件是已经用jq封装好的组件,可以直接调用api
-
- 列表组件是自己通过new的vue,结合element-ui完成的
项目需求
-
- 将地图和列表联动,达到在地图上操作数据或者在列表上操作数据时,另一个组件会立即做出响应
项目实践
-
- 既然是响应式,那自然而然绕不开Object.defineProperty以及Proxy了,因为传过来的是数组, 并且在联动的过程中必然涉及到数组的增删改,那么,根据实际情况,只能选择Proxy了
-
- 在拿到数据之后,将数据改造为代理数据,在里面增加拦截功能,当数据改变时调用改变视图的函数
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);
},
});
}