如何控制多个 toast 提示的展示
侧边栏壁纸
  • 累计撰写 1,061 篇文章
  • 累计收到 0 条评论

如何控制多个 toast 提示的展示

加速器之家
2024-10-20 / 0 评论 / 2 阅读 / 正在检测是否收录...

我们在平时会用弹窗或者 toast 对用户进行提示,而弹窗是属于强提示类型的(需要用户点击等交互后弹窗才消失),提供的信息量也大,而 toast 提示则属于弱提示类型(无论用户有没有看到,反正我提示了),仅进行小小的提醒。

弹窗类型的交互通常可以多个弹窗叠加,用户关闭一个后,再看下一个;而 toast 提示通常在同一时间只显示一个,那么如果同时多个 toast 需要提示时,怎么办?

  • ant design 中的做法是同时将多个 toast 放到一个容器里(没有该容器则创建,有则直接使用),从上往下都展示出来【ant design message】,
  • 我们是为了跟新闻客户端 APP 的提示更加贴近,同一时间只弹一个,其他的先缓存起来。

我们接下来把这两种方式都实现一下。

1. 先实现一个简单的 toast #

我们先来实现一个简单的 toast,然后再说如何控制多个 toast 的先后提示。

// 在浏览器上模拟toast提示
export const toast = (
    text: string | number,
    duration: number = 1800,
    container: HTMLElement = document.body
): Promise => {
    toastInstance = true;
    let div: HTMLElement = document.createElement('div');
    div.className = 'toast';
    div.style.cssText = `position: relative;
margin-top: 20px;
padding: 12px 20px;
border-radius: 5px;
background-color: rgba(255, 255, 255, 0.96);
color: #111111;
font-size: 16px;
line-height: 1.5;
white-space: nowrap;
text-align: center;`
; div && (div.innerHTML = text.toString()); container.appendChild(div); return new Promise((resolve) => { setTimeout(() => { div && div.parentNode && div.parentNode.removeChild(div); // 固定时间后消失 toastInstance = false; resolve(); }, duration); }); };

用 div 模拟一个 toast。

2. 展示多个 toast 的方式 #

2.1 将多个 toast 都展示出来 #

这里我们的重点是要创建一个 toast 所在的唯一的容器,然后给容器一个定位:

let toastContainer: any = null;
export const getToastContainer = () => {
    if (toastContainer) {
        return toastContainer;
    }
    toastContainer = document.createElement('div');
    toastContainer.style.cssText = `position: fixed;
top: 20px;
left: 50%;
transform: translate3d(-50%, 0, 0);
z-index: 9999;`
; document.body.appendChild(toastContainer); return toastContainer; };

最后给一个总入口,把单个 toast 放在容器里:

const message = (text) => {
    getToastContainer();
    toast(text, 1800, toastContainer);
};

可以查看 demo 效果:类 ant design 的 toast 提示

2.2 同时只显示一个 toast 提示 #

上面的提示方式在 PC 端还可以,但是在移动端的小屏幕上,同时显示多个会显得比较拥挤,因此我们这里同时最多只显示一个 toast 提示,上一个消失之后,再展示下一个 toast 提示。

这里我们要对toast稍微改造下:

  1. 同一时间只能创建一个 toast,因此添加一个 toastInstance 变量进行控制;
  2. 修改 toast 的样式;
+ let toastInstance = false;
const toast = (text, duration = 1800, container = document.body) => {
+    if (toastInstance) {
+        return;
+    }
+    toastInstance = true;
    let div = document.createElement('div');
    div.className = 'toast';
    div.style.cssText = `position: fixed;
padding: 12px 20px;
border-radius: 5px;
+ top: 20px;
+ left: 50%;
+ transform: translate3d(-50%, 0, 0);
background-color: rgba(255, 255, 255, 0.96);
box-shadow: 0 0 2px #666666;
color: #111111;
font-size: 16px;
line-height: 1.5;
white-space: nowrap;
text-align: center;`
; div && (div.innerHTML = text.toString()); container.appendChild(div); return new Promise((resolve) => { setTimeout(() => { div && div.parentNode && div.parentNode.removeChild(div); // 固定时间后消失 + toastInstance = false; resolve(); }, duration); }); };

然后通过一个方法和缓存来控制 toast 的显示:

let toastList = []; // 后面的提示先缓存起来
const toastWaterFall = async (text) => {
    if (toastInstance) {
        toastList.push(text); // 若当前toast正在进行,则缓存
    } else {
        await toast(text); // 否则展示toast提示

        if (toastList.length) {
            while (toastList.length) {
                await sleep(300); // 延迟一段时间
                await toast(toastList.shift() + '');
            }
        }
    }
};

可以点击链接查看 demo:同时最多只展示一个 toast 提示

3. 总结 #

关于 toast 的设计还有很多要考虑的问题,这里我们也是探讨了如何控制多个 toast 的展示问题。

0

评论

博主关闭了当前页面的评论