夺命连续弹框的自救之路

733 阅读2分钟

如果不是想写屎堆一样的代码,如果不是想不给自己挖坑,至于吗?只能怪产品需求很大众但是是真的很🤮恶心

5B6995DB03FF6388AB5833223ED46C77.jpg 瑟瑟发抖

就事论事如何才简单明了的解决这夺命的连续弹框的道路上,同时希望自己的代码不是屎堆,且可以给后背乘凉呢,showTime 大佬勿喷 🐶 (狗头保命)

发布订阅+组合+控制

撸起袖子直接淦(Vue3走起)

  1. 想法:首先将弹框当成子集,我们只需要知道接下来的步骤需要弹出哪些弹框,将其Push到List中,然后通过Controler去迭代展示弹框的展示

  2. 实现单个弹框的展示逻辑(发布订阅 → 告诉Controler执行下一步操作)

    首先定义一个CreatMonitorSpringView类,需要

  // 弹框类型枚举
  enum CreatMonitorSpringViewType {
      CUSTOMS_SUCCESS, // 闯关成功
      CUSTOMS_EJECT, // 闯关失败
  }

  class CreatMonitorSpringView {
      // 当前需要弹框的集合
      currtDialogs: CurrtExamples = {
        creatMonitorSpringViews: []
      };

      type: CreatMonitorSpringViewType;

      valueResolve: ((value: unknown) => void) | null = null;

      value: Ref<boolean> = ref(false);

      delayed = 0;

      callBackCollection: CallBackState = {};

      get viewControl() {
        return readonly(this.value);
      }

  constructor(type: CreatMonitorSpringViewType, callBackAsg: CallBackState = {}, delayed = 0) {
    this.delayed = delayed;
    this.type = type;
    this.callBackCollection = callBackAsg;
    //   监听弹框
    watch(this.value, async () => {
      // 当值改变的回调函数
      if (!this.value.value) {
        this.valueResolve && this.valueResolve(null);
        this.closeCallback();
      } else {
        if (this.callBackCollection.callback) {
          const data = this.callBackCollection.callback(this.close.bind(this));
          if (data instanceof Promise) {
            await data;
          }
        }
      }
    });
  }
  //   弹出弹框或者关闭弹框
  async open() {
    if (this.callBackCollection.beforeCallback) {
      const data = this.callBackCollection.beforeCallback(this.close.bind(this));
      if (data instanceof Promise) {
        const result = await data;
        if (!result && typeof result === 'boolean') return;
      } else {
        if (!data && typeof data === 'boolean') return;
      }
    }
    return new Promise((resolve) => {
      this.value.value = true;
      this.valueResolve = resolve.bind(this);
    });
  }

  close() {
    this.value.value = false;
  }
  //   关闭回调
  async closeCallback() {
    if (this.callBackCollection.afertCallback) {
      const data = this.callBackCollection.afertCallback(this.currtDialogs);
      if (data instanceof Promise) {
        await data;
      }
    }
    this.valueResolve = null;
  }
}

通过监听value值的变化,去设立钩子函数

   interface CallBackState {
      beforeCallback?: (Function, ...asg: any[]) => Promise<boolean | void> | boolean | void;
      callback?: (Function, ...asg: any[]) => unknown;
      afertCallback?: (item: CurrtExamples) => unknown;
}

最后将控制权交给Controler

const useGeneratorView = (creatMonitorSpringViews: CreatMonitorSpringView[]) => {
  const currtSprType = ref<CreatMonitorSpringViewType>();
  const taskCallView = async (callback?) => {
    // 避免Ref转化成ToRef 且不丢响应
    const currtExample = { creatMonitorSpringViews };
    for (const item of currtExample.creatMonitorSpringViews) {
      // 注入当前的dialog所有弹框, 防止动态逻辑需要新增弹框
      currtSprType.value = item.type;
      item.currtDialogs = currtExample;
      await delayedPromiseFun(item.delayed);
      await item.open();
    }
    callback && callback();
  };
  return { taskCallView, currtSprType };
};

const delayedPromiseFun = (delay = 0) => new Promise((resolve) => setTimeout(resolve, delay));

这样我们只需关注需要哪些弹框的展示塞入即可

useGeneratorView([
  new CreatMonitorSpringView(CreatMonitorSpringViewType.CUSTOMS_SUCCESS),
  new CreatMonitorSpringView(CreatMonitorSpringViewType.CUSTOMS_EJECT)
]);