当前位置: 首页 > article >正文

推荐一个小而美的 Toast 插件 (一键复制使用)

一. 前言

推荐一个小而美的 Toast 插件。考虑到该演示的简易性质,我们决定不引入任何第三方用户界面(UI)库,这带来了如何实现非侵入式的用户通知(如 toast 提示)。

通常情况下,对于简单的警告或通知,开发者可能会依赖浏览器自带的 alert 函数。然而,alert 弹窗会强制暂停用户的交互流程,提供较差的用户体验;并且它不适合处理多个同时出现的通知,也缺乏对不同通知类型的视觉区分能力。

尽管网络上有许多现成的解决方案,例如基于 jQuery 时代的独立 toast 插件和 Bootstrap 库中的实现,但这些选项要么过时,要么过于庞大,不符合我们对轻量化简洁性的追求。因此,我决定开发一个自定义的、轻巧且易于使用的 toast 组件,以满足我们的特定需求。

新组件不仅将提升用户体验,确保通知不会打断用户的操作流程,还将支持多种通知类型,比如成功、警告和错误信息等,从而为用户提供更加直观的信息反馈。通过这个过程,我们希望不仅能解决当前的问题,还能为未来类似的需求创建一个可复用的解决方案。

二. 设计理念

秉承 autofit.js 的设计理念,我继续选择使用纯 JavaScript 实现新项目,以确保代码的极致精简和广泛的兼容性。在此基础上,我还特别为该项目编写了 TypeScript 声明文件(.d.ts),从而全面支持 TypeScript 开发环境。

由此,autolog.js 应运而生:一个不仅继承了前作的高效与兼容性优势,还进一步增强了对现代开发流程支持的全新库。

图片

 

autolog.js 由两部分组成:一段极简的 JavaScript 和一段精炼的 CSS。经过 gzip 压缩后,整个包的体积仅为 1.40 KB,确保了快速加载和高效的性能表现。

文末可复制源码

1. 源码 js 部分(v2.0.0)

const cssStr = `#autolog{display:flex;flex-direction:column;align-items:center;justify-content:flex-start;pointer-events:none;width:100vw;height:100vh;position:fixed;left:0;top:0;z-index:9999999;cursor:pointer;transition:0.2s}#autolog span{pointer-events:auto;width:max-content;animation:fadein 0.4s;animation-delay:0s;border-radius:6px;padding:10px 20px;box-shadow:0 0 10px 6px rgba(0,0,0,0.1);margin:4px;transition:0.2s;z-index:9999999;font-size:14px;display:flex;align-items:center;justify-content:center;gap:4px;height:max-content}#autolog span.hide{opacity:0;pointer-events:none;transform:translateY(-10px);height:0;padding:0;margin:0}.autolog-warn{background-color:#fffaec;color:#e29505}.autolog-error{background-color:#fde7e7;color:#d93025}.autolog-info{background-color:#e6f7ff;color:#0e6eb8}.autolog-success{background-color:#e9f7e7;color:#1a9e2c}.autolog-{background-color:#fafafa;color:#333}@keyframes fadein{0%{opacity:0;transform:translateY(-10px)}100%{opacity:1;transform:translateY(0)}}`
const svgIcons = {
warn: `<svg t="1713405237257" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2387" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M934.4 770.133333L605.866667 181.333333C586.666667 147.2 550.4 128 512 128c-38.4 0-74.666667 21.333333-93.866667 53.333333L89.6 770.133333c-19.2 34.133333-19.2 76.8 0 110.933334S145.066667 938.666667 183.466667 938.666667h657.066666c38.4 0 74.666667-21.333333 93.866667-57.6 19.2-34.133333 19.2-76.8 0-110.933334z m-55.466667 81.066667c-8.533333 14.933333-23.466667 23.466667-38.4 23.466667H183.466667c-14.933333 0-29.866667-8.533333-38.4-23.466667-8.533333-14.933333-8.533333-34.133333 0-49.066667L473.6 213.333333c8.533333-12.8 23.466667-21.333333 38.4-21.333333s29.866667 8.533333 38.4 21.333333l328.533333 588.8c8.533333 14.933333 8.533333 32 0 49.066667z" fill="#e29505" p-id="2388"></path><path d="M512 746.666667m-42.666667 0a42.666667 42.666667 0 1 0 85.333334 0 42.666667 42.666667 0 1 0-85.333334 0Z" fill="#e29505" p-id="2389"></path><path d="M512 629.333333c17.066667 0 32-14.933333 32-32v-192c0-17.066667-14.933333-32-32-32s-32 14.933333-32 32v192c0 17.066667 14.933333 32 32 32z" fill="#e29505" p-id="2390"></path></svg>`,
error: `<svg t="1713405212725" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1744" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M512 74.666667C270.933333 74.666667 74.666667 270.933333 74.666667 512S270.933333 949.333333 512 949.333333 949.333333 753.066667 949.333333 512 753.066667 74.666667 512 74.666667z m0 810.666666c-204.8 0-373.333333-168.533333-373.333333-373.333333S307.2 138.666667 512 138.666667 885.333333 307.2 885.333333 512 716.8 885.333333 512 885.333333z" fill="#d93025" p-id="1745"></path><path d="M657.066667 360.533333c-12.8-12.8-32-12.8-44.8 0l-102.4 102.4-102.4-102.4c-12.8-12.8-32-12.8-44.8 0-12.8 12.8-12.8 32 0 44.8l102.4 102.4-102.4 102.4c-12.8 12.8-12.8 32 0 44.8 6.4 6.4 14.933333 8.533333 23.466666 8.533334s17.066667-2.133333 23.466667-8.533334l102.4-102.4 102.4 102.4c6.4 6.4 14.933333 8.533333 23.466667 8.533334s17.066667-2.133333 23.466666-8.533334c12.8-12.8 12.8-32 0-44.8l-106.666666-100.266666 102.4-102.4c12.8-12.8 12.8-34.133333 0-46.933334z" fill="#d93025" p-id="1746"></path></svg>`,
info: `<svg t="1713405208589" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1582" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M853.333333 138.666667H170.666667c-40.533333 0-74.666667 34.133333-74.666667 74.666666v512c0 40.533333 34.133333 74.666667 74.666667 74.666667h151.466666V917.333333c0 12.8 8.533333 25.6 19.2 29.866667 4.266667 2.133333 8.533333 2.133333 12.8 2.133333 8.533333 0 17.066667-4.266667 23.466667-10.666666l136.533333-138.666667H853.333333c40.533333 0 74.666667-34.133333 74.666667-74.666667V213.333333c0-40.533333-34.133333-74.666667-74.666667-74.666666z m10.666667 586.666666c0 6.4-4.266667 10.666667-10.666667 10.666667H501.333333c-8.533333 0-17.066667 4.266667-23.466666 10.666667l-89.6 93.866666V768c0-17.066667-14.933333-32-32-32H170.666667c-6.4 0-10.666667-4.266667-10.666667-10.666667V213.333333c0-6.4 4.266667-10.666667 10.666667-10.666666h682.666666c6.4 0 10.666667 4.266667 10.666667 10.666666v512z" fill="#0e6eb8" p-id="1583"></path><path d="M512 490.666667H298.666667c-17.066667 0-32 14.933333-32 32S281.6 554.666667 298.666667 554.666667h213.333333c17.066667 0 32-14.933333 32-32S529.066667 490.666667 512 490.666667zM672 341.333333H298.666667c-17.066667 0-32 14.933333-32 32S281.6 405.333333 298.666667 405.333333h373.333333c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32z" fill="#0e6eb8" p-id="1584"></path></svg>`,
success: `<svg t="1713405224326" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2225" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16"><path d="M512 74.666667C270.933333 74.666667 74.666667 270.933333 74.666667 512S270.933333 949.333333 512 949.333333 949.333333 753.066667 949.333333 512 753.066667 74.666667 512 74.666667z m0 810.666666c-204.8 0-373.333333-168.533333-373.333333-373.333333S307.2 138.666667 512 138.666667 885.333333 307.2 885.333333 512 716.8 885.333333 512 885.333333z" fill="#1a9e2c" p-id="2226"></path><path d="M701.866667 381.866667L448 637.866667 322.133333 512c-12.8-12.8-32-12.8-44.8 0-12.8 12.8-12.8 32 0 44.8l149.333334 149.333333c6.4 6.4 14.933333 8.533333 23.466666 8.533334s17.066667-2.133333 23.466667-8.533334l277.333333-277.333333c12.8-12.8 12.8-32 0-44.8-14.933333-12.8-36.266667-12.8-49.066666-2.133333z" fill="#1a9e2c" p-id="2227"></path></svg>`
}
const autolog = {
  log(text, type = '', time = 2500) {
    if (typeof type === 'number') {
      time = type
      type = ''
    }
    let mainEl = getMainElement()
    let el = document.createElement('span')
    el.className = `autolog-${type}`
    el.innerHTML = svgIcons[type] + text
    mainEl.appendChild(el)
    setTimeout(() => {
      el.classList.add('hide')
    }, time - 500)
    setTimeout(() => {
      mainEl.removeChild(el)
      el = null
    }, time)
  }
}
function getMainElement() {
let mainEl = document.querySelector('#autolog')
if (!mainEl) {
    mainEl = document.createElement('div')
    mainEl.id = 'autolog'
    document.body.appendChild(mainEl)
    let style = document.createElement('style')
    style.innerHTML = cssStr
    document.head.insertBefore(style, document.head.firstChild)
  }
return mainEl
}
exportdefault autolog

以上就是 autolog.js 的完整 JavaScript 代码。如您所见,它仅导出了一个名为 log 的方法,调用此方法时只需要提供一个必填参数。

让我来解释一下这段代码的工作流程:

  1. 可选参数处理:由于 log 方法支持两个可选参数(time 和 type),代码首先会检查用户传递了哪些可选参数。这使得在使用时可以根据需要单独传递 time 或者 type 参数,提供了灵活性。

  2. 主容器管理:通过 getMainElement 方法获取或创建用于容纳所有日志条目的主容器。如果主容器不存在,则自动创建。这种方式省去了用户手动初始化的步骤,避免了传统插件中常见的 init 方法需求,简化了集成过程。

  3. 日志元素生成:为每次的日志记录创建一个新的 span 元素,用于展示具体的日志内容。这样做保证了每个日志项都是独立的 DOM 节点,便于管理和样式控制。

  4. 优雅退出机制:采用两个定时器来实现日志条目的优雅退出。第一个定时器会在清除元素前 0.5 秒为其添加退场动画,确保视觉上的平滑过渡;第二个定时器负责彻底移除该元素,并将引用置为 null,以此断开与 DOM 的连接,防止游离 DOM 节点的产生和潜在的内存泄漏问题。

尤其值得注意的是,CSS 部分在 autolog.js 中扮演着至关重要的角色,它不仅定义了日志条目的外观样式,还承载了关键的显示逻辑,包括但不限于动画效果等。

2. css 部分

实力宠粉,主打一个听劝!

图片

 

昨天评论区掘友建议 all in js,今天一早我已经改完了,并发了 2.0.0 版本,把 css 放到了 js 里,图标都换成了 svg 也放到了 js 里。

由此可见,你也可以重写这些 css,为他们添加不同的颜色。

没有什么巧妙的设计,也没有什么精致的构思,朴实无华的一百多行代码而已,希望这些代码可以帮到各位。

三. 安装和使用

使用也非常简单,只需引入 ~两个文件~ 一个文件。

1. 安装

npm i autolog.js

2. 使用

import autolog from 'autolog.js'

autolog.log('Hi,this is a normal tip')
autolog.log('Hello World', 'success', 2500)
// 其中 "success" 和 2500 都是可选项

四. 完整效果演示

图片

 

五. 示例代码,可直接复制使用

代码仅供演示,实际项目中按照规范引入使用!

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>autolog.js Demo</title>
    <link rel="shortcut icon" href="https://raw.githubusercontent.com/Larryzhu-dev/autolog.js/main/autolog.svg" />
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
        text-decoration: none;
      }
      body {
        background: #1f1f1f;
        overflow: hidden;
      }
      button {
        background: none;
        border: none;
        outline: none;
        background: #eee;
        padding: 6px 12px;
        border-radius: 6px;
        cursor: pointer;
        transition: 0.2s;
      }
      input {
        background: #eee;
        padding: 6px 12px;
        border-radius: 6px;
        border: none;
        outline: none;
        width: 120px;
      }
      button:hover {
        opacity: 0.9;
      }
      .autologBox,
      .autofitBox {
        display: flex;
        flex-direction: column;
        gap: 20px;
        align-items: center;
        justify-content: center;
        padding-top: 200px;
      }
      .pluginInfos {
        color: #999;
      }
      .customText {
        color: #fff;
        font-size: 20px;
      }
      .autologBox .logo img {
        width: 300px;
      }
      .buttons {
        display: flex;
        justify-content: center;
        gap: 12px;
      }
      .codeBlock {
        background: #181818;
        color: #cccccc;
        padding: 12px;
        border: 1px solid #333;
        border-radius: 12px;
        display: flex;
        align-items: flex-start;
        justify-content: flex-start;
        gap: 12px;
      }
      .logo {
        display: flex;
        justify-content: center;
        align-items: center;
        width: 100%;
      }
      .logo img {
        width: 160px;
      }
    </style>
    <script src="https://unpkg.com/autolog.js@2.2.1/autolog.min.js"></script>
</head>
<body>
    <div class="autologBox">
      <div class="logo">
        <a href="https://github.com/LarryZhu-dev/autolog.js" target="_blank">
          <img src="https://raw.githubusercontent.com/Larryzhu-dev/autolog.js/main/autolog.svg" alt="indexPages" />
        </a>
      </div>
      <div class="pluginInfos">
        <span>autolog.js 一款轻量化小弹窗插件 1.40kb(gzip)</span>
      </div>
      <div class="customText">
        <input type="text" placeholder="请输入文本" id="text" />
        <input type="text" placeholder="请输入时长" id="time" />
      </div>
      <div class="buttons">
        <button class="success" onclick="showLog()">素框</button>
        <button class="success" onclick="showLog('success')">成功</button>
        <button class="error" onclick="showLog('error')">错误</button>
        <button class="warn" onclick="showLog('warn')">警告</button>
        <button class="info" onclick="showLog('info')">公告</button>
      </div>
      <div class="install">
        <div class="codeBlock">
          <span>npm install autolog.js</span>
          <button onclick="copy()">copy</button>
        </div>
      </div>
    </div>

    <script>
      autolog.log('hi,autolog.js!', 'info')
      function showLog(logType) {
        let text = document.getElementById('text').value
        let time = document.getElementById('time').value
        autolog.log(text || 'Hello World', logType || '', Number(time) || 2500)
      }
      function copy() {
        const code = document.querySelector('.codeBlock span').innerText
        const input = document.createElement('input')
        input.value = code
        document.body.appendChild(input)
        input.select()
        document.execCommand('copy')
        document.body.removeChild(input)
        autolog.log('复制成功', 'success', 2000)
      }
    </script>
</body>
</html>

http://www.kler.cn/a/513400.html

相关文章:

  • 递归练习六(普通练习11-15)
  • Hnu电子电路实验2
  • 网络编程 | UDP组播通信
  • 2024人工智能AI+制造业应用落地研究报告汇总PDF洞察(附原数据表)
  • PHP:从入门到进阶的全方位指南
  • JSON-stringify和parse
  • Dart语言的学习路线
  • YOLOv10-1.1部分代码阅读笔记-dist.py
  • 61,【1】BUUCTF WEB BUU XSS COURSE 11
  • 大牙的2024年创作总结
  • 求解ssp 问题建模
  • 个人职业发展与AI赋能的前端开发
  • 交换机Console密码忘记无法登录设备怎么办?
  • ubuntu16.04 VSCode下cmake+clang+lldb调试c++
  • 线程池实现
  • 36. K11364 剑法
  • Erlang语言的面向对象编程
  • 以 RFID 为钥,开启民兵装备管理的科技之门
  • linux 下tensorrt的yolov8的前向推理(python 版本)的实现
  • 【Linux】多线程(一)
  • JavaScript笔记进阶篇01——作用域、箭头函数、解构赋值
  • Java 中的同步与并发工具类
  • JAVA-Exploit编写(8-10)--http-request库编写exp批量利用
  • 后端:MyBatis
  • Hive: Hive的优缺点,使用方式,判断Hive是否启动(jps),元数据的存储,Hive和Hadoop的关系
  • Elasticsearch 中,分片(Shards)数量上限?副本的数量?