项目内有些页面会存在一些列表类的数据,其中大都采用了分页结构,导致内容的高度和可视区的位置是随着用户的操作而改变的,当用户进入下一个页面对列表相关的内容进行某些操作又返回上一页的时候,为了保证数据的实时性就要将列表的刷新放在 onShow 内,这样就会导致生成的高度被重置,页面闪烁,定位消失,那么这种体验感能否进行优化呢?
首先从业务场景来看,当 A B C 页面发生互相来回切换,用户操作时,三个页面内的数据并不一定是会互相影响的,例如从 作品列表 跳转 详情 再到 个人中心,如果期间不发生对作品诸如 点赞、收藏、删除等类似操作,切换页面的时候是完全没必要对列表进行数据刷新的,所以基于此可以将列表的刷新频率大大降低,至于该刷新列表数据的页面就应该让它刷新,闪烁刷新其实也是潜意识里告诉用户操作后,任何页面相关改变的数据都是新的,并不一定就会带来负面体验
难点在于,
- 列表数据的加载是需要考虑页面所处的两种状态的,一个是初始化,一个是切回;
- 当内容发生更改时,页面栈内存在的包含列表的页面都需要更新;
项目里采用的做法是结合 onLoad + onShow + onUnLoad 三个生命周期钩子配合缓存和页面栈的判断来实现更细小粒度的控制,从而尽可能降低对列表内容的刷新频率
具体做法如下:
<!-- 定义存在列表页面枚举 -->
enum RefreshWorksListENUM {
"pages/index/index" = 1,
"pages/profileCenter/index",
"subPackages/profileCenter/index",
"subPackages/search/index",
"subPackages/worksDetail/index",
}
<!-- 在触发作品内容变更的接口内将缓存 refreshWorks 设为 true -->
/**
* @description: 点赞作品
*/
export const likeWork = async (data: WorksSearchReqJSON): Promise<boolean> => {
Taro.setStorageSync("refreshWorks", true);
return await request.post("works/likes", data);
};
<!-- 在枚举页面 onLaod 时默认加载列表数据,缓存 loadCurPageWorks 设为 true -->
useLoad(() => Taro.setStorageSync("loadCurPageWorks", true));
<!--
在枚举页面 onShow 时同时判断是否存在内容变更(refreshWorks),或者是处于初始化
(因为返回页面不触发 onLoad,但初始化会,因此判断 loadCurPageWorks 状态即可知晓是返回还是初始化),
在初始化完成后要将 loadCurPageWorks 设为 false 供下个页面判断
-->
if (
Taro.getStorageSync("refreshWorks") ||
Taro.getStorageSync("loadCurPageWorks")
) {
await getBannerList({
position: 101,
});
await getTabList({ userId });
Taro.setStorageSync("loadCurPageWorks", false);
}
<!--
用户返回上个页面,本页面销毁时需要判断页面栈内是否存在相关列表页面,
若存在则继续保留 refreshWorks 状态
-->
useUnload(() => setRefreshWorks());
/**
* @description: 返回上一个页面前,更新是否需要刷新作品的缓存状态
*/
const setRefreshWorks = () => {
const refreshWorks =
Taro.getStorageSync("refreshWorks") &&
Taro.getCurrentPages().some(({ route = "" }) => {
return !!RefreshWorksListENUM[route];
});
Taro.setStorageSync("refreshWorks", refreshWorks);
};
这样,从对 页面初始化和页面切回 两种状态的处理,便完成了一个完整的判断是否需要刷新列表数据的逻辑链路
小概率发生的问题,小程序页面栈的最大数量为 10,意味着理论上通过对页面栈进行列表页面枚举匹配可能会出现遗漏,但实际业务中,可以通过路由跳转的不同方式来杜绝超出10层页面栈,或者维护一个自定义的页面栈