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

蚊子前端博客
发布于 2020-07-20 13:59
当需要同时展示多个toast提示,我们应该如何控制呢?

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

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

  • ant design 中的做法是同时将多个 toast 放到一个容器里(没有该容器则创建,有则直接使用),从上往下都展示出来【ant design message】,

  • 我们是为了跟新闻客户端 APP 的提示更加贴近,同一时间只弹一个,其他的先缓存起来。

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

1. 先实现一个简单的 toast

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

COPYJAVASCRIPT

// 在浏览器上模拟toast提示 export const toast = ( text: string | number, duration: number = 1800, container: HTMLElement = document.body ): Promise<any> => { 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 所在的唯一的容器,然后给容器一个定位:

COPYJAVASCRIPT

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 放在容器里:

COPYJAVASCRIPT

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

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

2.2 同时只显示一个 toast 提示

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

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

  1. 同一时间只能创建一个 toast,因此添加一个 toastInstance 变量进行控制;

  2. 修改 toast 的样式;

COPYJAVASCRIPT

+ 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 的显示:

COPYJAVASCRIPT

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 的展示问题。

标签:
阅读(1260)

公众号:

qrcode

微信公众号:前端小茶馆