应将 showWarning 函数定义在调用前,确保执行顺序正确:移至前、用window.onload包裹、显式挂载到window、改用函数声明或ES模块导入,避免SSR环境直接执行。

如何封装一个全局可用的 showWarning 函数
不能直接覆盖 alert,也不该把 DOM 节点写死在 HTML 里。真正可复用的全局警告函数,必须满足:动态创建、自动清理、支持多次调用互不干扰、且不污染全局命名空间(除非你明确要挂到 window 上)。
核心做法是封装成一个立即执行的模块,返回函数并选择性挂载:
- 用
IIFE包裹,避免变量泄漏;内部用document.createElement动态生成遮罩和弹窗 - 消息内容统一用
textContent设置,杜绝 XSS 风险(别用innerHTML渲染用户输入) - 关闭逻辑必须包含三处:关闭按钮点击、遮罩层点击(仅当点击自身)、
Escape键监听 - 若需全局调用,显式赋值给
window.showWarning = ...;否则导出为 ES 模块或通过构建工具管理
示例最小可行封装:
const showWarning = (message) => {
const overlay = document.createElement('div');
overlay.className = 'warning-overlay';
const dialog = document.createElement('div');
dialog.className = 'warning-dialog';
dialog.innerHTML = `
<p class="warning-text">⚠️ ${message}</p>
<button class="warning-close">×</button>
`;
overlay.appendChild(dialog);
document.body.appendChild(overlay);
const close = () => {
document.body.removeChild(overlay);
};
overlay.addEventListener('click', (e) => e.target === overlay && close());
dialog.querySelector('.warning-close').addEventListener('click', close);
document.addEventListener('keydown', (e) => e.key === 'Escape' && close());
};
// 全局暴露(仅当需要时)
if (typeof window !== 'undefined') {
window.showWarning = showWarning;
}
showWarning 调用时报 ReferenceError: showWarning is not defined 怎么办
这个错误只说明一件事:函数还没定义,你就调用了。不是语法错,是执行顺序问题。
常见触发场景和对应解法:
-
写在或 script 标签之前 → 把 script 移到前,或加window.onload包裹初始化 - 函数定义在模块文件里(如
utils.js),但没用import或script type="module"加载 → 改用传统<script src="utils.js"></script>,且确保它在按钮之前加载 - 用了
const showWarning = ...但没挂到window,却在内联事件里调用 → 改成function showWarning() {...}(函数声明会提升),或显式挂载 - SSR 环境(如 Next.js、Nuxt)中服务端渲染时执行了该函数 → 加运行时判断
if (typeof window !== 'undefined') { ... }
为什么不能用 confirm() 替代 showWarning
confirm() 不是警告框,它是确认框——返回 true 或 false,语义和交互目的完全不同。强行用它做警告,会带来三个硬伤:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 用户看到“确定/取消”按钮,会产生操作预期,但你的业务逻辑其实不需要用户做选择 → 违反用户心智模型
- 点击“取消”时返回
false,若未显式拦截(如if (!confirm(...)) return false),后续代码照常执行 → 极易引发误操作 - 它仍属原生阻塞式对话框:移动端常被拦截、无法定制样式、不支持图标或富文本、无障碍支持弱
真要带操作反馈的警告(比如“超支了,是否继续?”),应该封装一个 showConfirm,和 showWarning 分开维护,不要混用。
警告框关闭后还占内存?DOM 和焦点残留怎么清
这是线上最隐蔽的问题:视觉上关了,但实际没真正卸载。后果包括焦点卡死、读屏软件重复播报、内存泄漏。
关键动作只有两个,缺一不可:
- 必须调用
element.remove()(不是element.style.display = 'none')→ 否则节点还在 DOM 树里,仍可能被querySelectorAll扫到、被屏幕阅读器聚焦 - 关闭后手动恢复焦点:记录打开前的
document.activeElement,关闭后.focus()回去;若原元素已销毁,退回到document.body或首个可聚焦元素
尤其注意异步场景:如果警告由 fetch 成功回调触发,而用户在请求期间已跳转页面,document.body.appendChild 会失败,需加 if (document.body) 守卫。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










