window.alert 是瀏覽器原生方法,內部實現為 Native Code,無法獲取、修改其樣式、佈局、按鈕文字。唯一可行路徑:**覆寫 `window.alert`**,用自定義 HTML/CSS/JS 彈窗完全替換。
document.body.appendChild()。element.style.cssText 批量設定,避免 IE8 渲染 Bug。;(function (win) {
// 1. 預編譯階段立即覆寫,確保所有 alert 走自定義邏輯
var nativeAlert = win.alert;
win.alert = function (msg) {
showCustomAlert(String(msg == null ? '' : msg));
};
// 2. 單例模式:全頁只有一套 DOM
var alertBox = null, mask = null, btn = null;
function ensureDOM() {
if (alertBox) return;
mask = document.createElement('div');
alertBox = document.createElement('div');
var msgBox = document.createElement('div');
btn = document.createElement('button');
// 結構組裝
alertBox.appendChild(msgBox);
alertBox.appendChild(btn);
document.body.appendChild(mask);
document.body.appendChild(alertBox);
// 3. 樣式統一用 cssText,解決 IE8 不支援 style.xxx 寫法
var css = {
mask: 'position:fixed;top:0;left:0;width:100%;height:100%;background:#000;opacity:.5;filter:alpha(opacity=50);z-index:9999;',
box: 'position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);background:#fff;padding:20px 30px;border-radius:4px;box-shadow:0 2px 10px rgba(0,0,0,.2);z-index:10000;min-width:260px;text-align:center;',
msg: 'font-size:14px;color:#333;line-height:1.5;margin-bottom:18px;word-break:break-all;',
btn: 'padding:6px 24px;background:#1890ff;color:#fff;border:none;border-radius:3px;cursor:pointer;font-size:14px;'
};
mask.style.cssText = css.mask;
alertBox.style.cssText = css.box;
msgBox.style.cssText = css.msg;
btn.style.cssText = css.btn;
btn.innerHTML = '確定';
// 4. 事件:點擊確定銷毀
btn.onclick = function () {
document.body.removeChild(mask);
document.body.removeChild(alertBox);
alertBox = mask = btn = null; // 釋放引用,下次重建
};
}
function showCustomAlert(text) {
ensureDOM();
alertBox.querySelector('div').textContent = text; // 更新訊息
// 重新插入(若上次已移除)
if (!document.body.contains(mask)) {
document.body.appendChild(mask);
document.body.appendChild(alertBox);
}
}
})(window);
| 技術點 | 說明 |
|---|---|
| 立即執行函數 (IIFE) | 形成閉包,避免污染全局變數;傳入 win 參數壓縮後更小 |
| 預編譯期覆寫 | var nativeAlert = win.alert; win.alert = ... 放在 IIFE 頂部,確保腳本載入瞬間生效 |
| 單例 DOM | 首次調用才創建,後續復用;關閉時移除 DOM 並置空引用,防記憶體洩漏 |
| cssText 批量寫樣式 | IE8 不支援 el.style.transform 等屬性寫法,cssText 字串解析無此問題 |
| transform + -ms-transform | 垂直水平居中,IE9+ 支援標準,IE9 需前綴 |
| filter:alpha(opacity=50) | IE8 透明度兼容 |
win.alert = function (msg, options) {
options = options || {};
showCustomAlert({
title: options.title || '提示',
message: msg,
onConfirm: options.onConfirm || function () {},
confirmText: options.confirmText || '確定',
cancelText: options.cancelText, // 若提供則顯示取消按鈕
onCancel: options.onCancel
});
};
內部 showCustomAlert 根據配置動態渲染按鈕區,onConfirm/onCancel 執行後銷毀彈窗。
<head> 最早載入,或用 defer 確保 DOMContentLoaded 前執行。window.showCustomAlert,子頁面調用 parent.showCustomAlert()。top: 50%; transform: translateY(-50%) 並在 focus 時 scrollIntoView。「造假」替換原生 alert 是前端工程化常見技巧:**不修改不可變的原生實現,而是在上層攔截並提供可控替代品**。同理可實現自定義 confirm、prompt、onbeforeunload 等,統一專案 UI 風格並擴展業務能力。