Miniprogram List Local Update
小程序列表经常遇到需要局部刷新的需求,具体场景如下:
列表单项带有操作按钮,操作后需刷新列表数据,且列表保持不滚动,仅需更新当前项的数据,分页需要保持;
从列表单项进入详情页面,在详情页面进行操作后,再次返回列表时,列表数据需要更新,且列表保持不滚动,仅需更新当前项的数据,分页需要保持;
问题思考和方案:
针对第一条,相对来说比较好处理,只要在单项操作后,接口返回更新后的数据,我们在现有列表中找出操作项数据,进行数据替换即可;这里需要注意,除了替换,还有可能是移除(状态变了,不在当前列表了或者真实删除了),需要同步移除本地列表对应的数据项;
第二条比较麻烦,在详情页操作了,返回列表时需要更新或者删除列表中具体一项,首先想到的就是通过 EventChannel 在列表页和详情页建立通讯,表面看起来好像确实能解决,但仔细推敲,其实是行不通滴;假如操作是在详情页之后的页面中进行,返回详情页需要更新,再返回列表页还需要更新,这里链路一长,就不靠谱了,很多列表都有类似的需求,太麻烦;
具体解决方案:
- 针对第一条,列表单项更新或者删除,以下为示例代码:
Page({
data: {
listData: [],
},
// 更新列表项
updataListItem(item, del = false) {
// 通过单项id, 找到该项在列表数组中的下标
const index = this.data.listData.findIndex(v => v.id === item.id);
if (index > -1) {
const updataKey = `listData[${index}]`;
// 不要通过filter过滤出新的列表,再更新整个列表,效率低,不推荐;应该只更新对应单项
this.setData({
optionItem: item,
[updataKey]: del ? null : item
});
} else {
// console.log("更新列表时,未找到对应项")
}
}
})
- 第二条我们的策略是在离开列表页面时,保持当前操作项的数据,在页面再次 show 时通过当前操作项查询最新的数据,并替换列表项;实现代码如下:
Page({
data: {
listData: [],
optionItem: {}
},
// 页面显示时
async onShow() {
// 操作项数据不为空时,查询当前项的最新数据
if (JSON.stringify(this.data.optionItem) !== "{}") {
await this.queryItemDataAndUpdataList(this.data.optionItem);
}
},
// 查看详情页面
handleGoDetails(event) {
const optionItem = event.currentTarget.dataset.item;
this.setData({
optionItem
});
wx.navigateTo({
url: `/pages/details/details?id=${optionItem.id}`,
});
},
// 通过id和列表查询条件获取最新数据,并更新列表数据
async queryItemDataAndUpdataList(item) {
// 省略实现代码 ...
this.updataListItem(itemData); // this.updataListItem(itemData, true);
},
// 更新列表项
updataListItem(item, del = false) {
// 通过单项id, 找到该项在列表数组中的下标
const index = this.data.listData.findIndex(v => v.id === item.id);
if (index > -1) {
const updataKey = `listData[${index}]`;
// 不要通过filter过滤出新的列表,再更新整个列表,效率低,不推荐;应该只更新对应单项
this.setData({
optionItem: item,
[updataKey]: del ? null : item
});
} else {
// console.log("更新列表时,未找到对应项")
}
}
})
注意事项:
- 分页不能通过 page 和 size 这种简单实现,需要更改为通过最后一条查询指定条数的方式实现;
- 列表存在不必要获取数据的问题(列表进入详情,详情页面无任何操作,再次返回,其实无需再次获取当前操作项的数据),但无伤大雅;
Read other posts