优雅的解决uniapp 页面多个组件调用同一个生命周期时的冲突

优雅的解决uniapp 页面多个组件调用同一个生命周期时的冲突

场景

当前有个页面,此页面有个 tabs,点击对应的 tabs 下面显示不同的模块,且每个模块都有上拉刷新的功能


<Statistics v-if="tabIndex == 1" />
<RealTime v-else-if="tabIndex == 2" />

要实现的效果: 上拉刷新时,值刷新对应的模块

处理方法

第一种:page 页面监听上拉刷新,然后通过 refs 调用对应的模块暴露出来的刷新方法(不推荐)

  1. 给所有子模块加上 ref
  2. 所有子模块暴露一个方法,用来刷新本模块的数据
  3. page 页面监听 onPullDownRefresh 事件,通过判断当前是哪个模块,来通过 ref 调用该模块的刷新方法

优点:

写起来简单

缺点:

  1. 如果模块过多则改起来非常恶心,只能一个一个加。
  2. 如果子模块中的数据不是子模块的,而是子模块的下级,或者下下级呢?那就需要从最底下的那一层开始暴露方法,然后一层一层的向上传递,最后传到 page 页面,写起来很复杂,而且耦合度太高了

第二种:在 page 页面定义一个对象来对所有的模块的上拉刷新进行管理

  1. page 页面定义一个对象,储存所有上拉刷新要触发的方法,再定义两个添加或删除属性的函数
// 下拉的方法组成的对象
const pullRefreshEvent = {};
/**
 * 添加事件
 * @param {string} key 事件的key(唯一值)
 * @param {function} fun 要执行的方法
 */
function addPullRefreshEvent(key, fun) {
  pullRefreshEvent[key] = fun;
}
function removePullRefreshEvent(key) {
  delete pullRefreshEvent[key];
}
  1. page 页面监听 onPullDownRefresh 事件,循环管理方法的对象,执行所有的方法
onPullDownRefresh(() => {
  for (let key in pullRefreshEvent) {
    pullRefreshEvent[key] && pullRefreshEvent[key]();
  }
});
  1. 父组件向外暴露方法,供子模块调用
defineExpose({
  addPullRefreshEvent,
  removePullRefreshEvent,
});
  1. 子模块拿到 page 页面,并在初始化时往管理上拉刷新方法的对象里添加唯一的 key 和要执行的方法
const page = getCurrentPage();
const pullRefreshEventKey = "realTime" + Date.now();

// 添加下拉刷新事件
page.$vm.addPullRefreshEvent(pullRefreshEventKey, async () => {
  // 如果当前选择的不是本模块,则不刷新
  //.....要做得事情
  uni.stopPullDownRefresh();
});
  1. 子模块在被销毁时移除掉上拉刷新的方法
onUnmounted(() => {
  page.$vm.removePullRefreshEvent(pullRefreshEventKey);
});

此方法主要是使用了面向对象的处理思维,高内聚,只需在需要注册事件的模块去进行添加或移除自己要执行的方法,把所有需要执行的方法交给 page 页面进行统一的管理,这样不会导致代码写的杂乱不易维护,这样即使组件模块套的再深也不会增加代码量!

你可能感兴趣的:(技术点,uni-app,javascript,前端)