需求是这样的(见下图),上面为常见的搜索条件,下面为穿梭框,穿梭框列表左侧右侧使用的是同一个列表,根据direction字段left和right控制在左侧还是右侧。
过去我的做法是点击查询,对接口重新进行请求,拿到数据后直接赋值,但是列表会重新渲染更新,原先选择的数据就消失了,很显然这样的交互是不友好的。
改进:选择完猪后切换条件重新点击查询不应清空已选中数据,也就是去右侧的数据依然在,但是左侧的数据需要过滤掉右侧已经选择的数据。
先模拟数据类型:
- arr1 为点击查询后,接口请求回来的数据(mock)
- arr2 为原有的数据,包括了direction字段,left为左侧数据,right为右侧的数据,我们只要right的数据
let arr1 = [
{
pigID: '1',
},
{
pigID: '2',
},
{
pigID: '3',
},
{
pigID: '4',
},
{
pigID: '5',
},
{
pigID: '6',
},
{
pigID: '7',
},
{
pigID: '8',
},
]
let arr2 = [
{
pigID: '2',
direction: 'left',
},
{
pigID: '3',
direction: 'right',
},
{
pigID: '7',
direction: 'right',
},
{
pigID: '9',
direction: 'right',
},
{
pigID: '10',
direction: 'right',
},
]
接下来是数据处理,见代码
let rightList = [] //取出direction为right的数据
let _set = new Set() //将right的数据里的pigID存在set中
//做取出操作
arr2.forEach((item) => {
if (item.direction == 'right') {
rightList.push(item)
_set.add(item.pigID)
}
})
//加到请求回来的数组中
arr1.push(...rightList)
//做数据里根据对象字段去重
var obj = {};
res = arr1.reduce(function (item, next) {
obj[next.pigID] ? '' : obj[next.pigID] = true && item.push(next);
return item;
}, []);
//去重后原有的direction的属性会消失,由于之前存在了_set中,所以遍历后再给加上
res.forEach((item) => {
if (_set.has(item.pigID)) {
item.direction = 'right'
}
})
//拿到想要的数据
console.log('结果', res);
步骤
- 这里首先我先将原有的数据且direction为right,取出来。
- push到请求回来的数据中,这时数据会有重复
- 去重操作,根据数组中对象去去重
- 由于去重后,原有的direction字典会消失,由于之前存在了_set中,所以遍历后再给加上。
- 拿到结果
写在最后
由于时间有限,可能不是最好的解决方案,代码还有优化空间,欢迎留言探讨。
附上我的前端笔记-blog。
前端笔记