uniapp踩坑 uni.showToast 和 uni.showLoading

uniapp踩坑 uni.showToast 和 uni.showLoading

一、问题描述

  • uni.showLoading 和 uni.showToast 混合使用时,showLoading和showToast会相互覆盖对方,调用hideLoading时也会将toast内容进行隐藏。

二、触发条件

  • 1.uniapp中使用自己封装的axois,拦截器使用 uni.showToast 做异常信息处理
  • 2.业务中使用 uni.showLoading 做业务处理
  • 3.当请求异常被catch抓到,使用 uni.hideLoading 清除 loading 时,异常信息 toast 会被覆盖掉。

三、解决思路

  • 小程序将Toast和Loading放到同一层渲染引起的,而且缺乏一个优先级判断,也没有提供Toast、Loading是否正在显示的接口供业务侧判断。所以我们自己实现这套逻辑,判断其中有一个已经渲染,泽不执行另一个。

四、实现方案

1.封装一下toast和loading

js 复制代码
/**
 * 显示消息提示框
 * @param title
 * @param options
 * @constructor
 */
export function Toast(title: string, options?: Partial<UniApp.ShowToastOptions>) {
  uni.showToast({
    title,
    duration: 1500,
    icon: 'none',
    mask: true,
    ...options,
  });
}

/**
 * 隐藏消息提示框
 */
export function HideToast() {
  uni.hideToast();
}

/**
 * 显示 loading 提示框
 * @param title
 * @param options
 * @constructor
 */
export function Loading(title: string, options?: Partial<UniApp.ShowLoadingOptions>) {
  uni.showLoading({
    title,
    mask: true,
    ...options,
  });
}

/**
 * 隐藏 loading 提示框
 */
export function HideLoading() {
  uni.hideLoading();
}

2.要加个变量控制toast和loading的优先级,最简单就是通过vue的全局状态管理来控制

js 复制代码
export const usePromptStore = defineStore({
  id: 'promptStore',
  state: (): IState => ({
    isShowLoading: false,
    isShowToast: false,
  }),
  getters: {
    getIsShowLoading: (state) => state.isShowLoading,
    getIsShowToast: (state) => state.isShowToast,
  },
  actions: {
    setIsShowLoading(val: boolean) {
      this.isShowLoading = val;
    },
    setIsShowToast(val: boolean) {
      this.isShowToast = val;
    },
  },
});

3.改造一下封装的toast和loading

js 复制代码
/**
 * 显示消息提示框
 * @param title
 * @param options
 * @constructor
 */
export function Toast(title: string, options?: Partial<UniApp.ShowToastOptions>) {
  const promptStore = usePromptStore();
  if (promptStore.disabledToast) return;

  if (promptStore.isShowLoading) {
    // Toast优先级更高
    HideLoading();
  }
  promptStore.setIsShowToast(true);
  uni.showToast({
    title,
    duration: 1500,
    icon: 'none',
    mask: true,
    ...options,
  });
  const timer = setTimeout(() => {
    promptStore.setIsShowToast(false);
    clearTimeout(timer)
  }, 1500);
}

/**
 * 隐藏消息提示框
 */
export function HideToast() {
  const promptStore = usePromptStore();
  promptStore.setIsShowToast(false);
  uni.hideToast();
}

/**
 * 显示 loading 提示框
 * @param title
 * @param options
 * @constructor
 */
export function Loading(title: string, options?: Partial<UniApp.ShowLoadingOptions>) {
  const promptStore = usePromptStore();
  if (promptStore.isShowToast) {
    // Toast优先级更高
    return;
  }
  promptStore.setIsShowLoading(true);
  uni.showLoading({
    title,
    mask: true,
    ...options,
  });
}

/**
 * 隐藏 loading 提示框
 */
export function HideLoading() {
  const promptStore = usePromptStore();

  if (promptStore.isShowToast) {
    // Toast优先级更高
    return;
  }
  promptStore.setIsShowLoading(false);
  uni.hideLoading();
}
相关推荐
漫天转悠1 小时前
Vue3项目中引入TailwindCSS(图文详情)
vue.js
qq_589568102 小时前
Echarts+vue电商平台数据可视化——后台实现笔记
vue.js·信息可视化·echarts
5hand3 小时前
Element-ui的使用教程 基于HBuilder X
前端·javascript·vue.js·elementui
GDAL3 小时前
vue3入门教程:ref能否完全替代reactive?
前端·javascript·vue.js
z千鑫4 小时前
【前端】详解前端三大主流框架:React、Vue与Angular的比较与选择
前端·vue.js·react.js
苹果醋35 小时前
React系列(八)——React进阶知识点拓展
运维·vue.js·spring boot·nginx·课程设计
王小王和他的小伙伴6 小时前
解决 vue3 中 echarts图表在el-dialog中显示问题
javascript·vue.js·echarts
好名字08216 小时前
前端取Content-Disposition中的filename字段与解码(vue)
前端·javascript·vue.js·前端框架
隐形喷火龙7 小时前
element ui--下拉根据拼音首字母过滤
前端·vue.js·ui
Simaoya8 小时前
【vue】css模拟玻璃球体效果(带高光)
前端·css·vue.js