小初 發表於 2025-6-15 17:59:00

改造jsp项目的alert框和confirm框

<h3 id="背景">背景</h3>
<p>之前项目的模态框改造完成,业务也想把页面中的提示框和确认框也改造一下;这里记录一下改造中的细节。</p>
<p>之前项目中的提示框和确认框用的是浏览器自带的 <code>alert</code> 和 <code>confirm</code>。改造之前无法支持业务一些复杂一点的需求,遂将之改造;</p>
<h3 id="实现">实现</h3>
<p>弹框层级设计参考了 <code>element</code> 和 <code>antd</code>,默认样式也是复用了他们的样式。层级从父到子如下所示</p>
<p><img src="https://img2024.cnblogs.com/blog/895887/202506/895887-20250615175358403-1108777326.png" alt="image" loading="lazy"></p>
<p><code>messageBoxWrap</code> 是弹出框包裹层和遮罩层。<code>messageBox</code> 是弹出框本身,里面包含了标题,内容,按钮。</p>
<p>而且因为默认 <code>confirm</code> 框会有返回值,所以这里改造后的也就返回了一个 <code>Promise</code>,并且只会 <code>resolve(true)</code> 或者 <code>resolve(false)</code>。</p>
<pre><code class="language-js">// type 区分是 alert 还是 confirm
// paramSting 表示提示框的内容,项目中没有自定义标题的需求,所以这里提示框都用统一的标题
function showMessagebox(type, paramString) {
//获取项目顶层的document,弹框显示需要覆盖顶层页面
var topDoc = window.top.document;
var mainFrameSet = topDoc.querySelector("#setMain");
var mainFrameSetParent = mainFrameSet.parentNode;
var topDocBody = window.top.document.body;
//创建弹框盒子,添加遮罩层
return new Promise((resolve, reject) =&gt; {
      // 具体实现
});
}
</code></pre>
<h4 id="注意事项">注意事项</h4>
<p>有几个注意的点是</p>
<ul>
<li>创建弹框时需要禁用键盘事件,弹框消失后启用键盘事件,防止弹框还未消失,使用 tab+enter去了其他页面的情况</li>
<li>需要避免有一个弹框存在的情况下,重复点击创建弹框</li>
</ul>
<p>然后是具体实现。</p>
<h4 id="添加默认样式">添加默认样式</h4>
<pre><code class="language-js">/*弹框的默认样式;*/
var messageBoxWrap_class = "modernMessagebox";
var messageBoxWrap_style =
"width:100%;height:100%;position:fixed;top:0;left:0;text-align:center;";
var messageBox_style =
"user-select:none;display: inline-block;width: 420px;padding: 10px 0px 20px;vertical-align: middle;background-color: #fff;border-radius: 4px;border: 1px solid #ebeef5;font-size:18px;box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);text-align: left;";
var header_style =
"padding: 10px 16px 10px;font-size:14px;display:flex;justify-content: space-between;";
var content_style = "padding: 10px 15px;color: #606266;font-size: 14px;";
var footer_style = "padding: 5px 15px 0;text-align: right;";
var button_style =
"display: inline-block;line-height: 1;wite-space: nowrap;cursor: pointer;background: #fff;border: 1px solid #dcdfe6;color: #606266;-webkit-appearance: none;text-align:center;box-sizing:border-box;outline:0;margin:0;transition:.1s;font-weight:500;padding:10px 16px;font-size:12px;border-radius:3px;";
var button_primary =
"color: #fff;background: rgb(11, 87, 208);border: 1px solid rgb(11, 87, 208);border-radius: 20px 20px;";

</code></pre>
<h4 id="创建-messageboxwrap添加遮罩层">创建 <code>messageBoxWrap</code>,添加遮罩层</h4>
<pre><code class="language-js">var messageBoxWrap = document.createElement("div");
messageBoxWrap.setAttribute("tabindex", "-1"); // 设置使其不能通过tab键聚焦
messageBoxWrap.className = messageBoxWrap_class + Date.now(); // 每次弹框的类名都是唯一的

// 使 messageBoxWrap 覆盖在顶层 window 上
messageBoxWrap.style = messageBoxWrap_style + ";width:" + topDocBody.clientWidth + "px;";
</code></pre>
<h4 id="创建-messagebox添加-headercontentfooter">创建 <code>messageBox</code>,添加 <code>header,content,footer</code></h4>
<p>1、创建<code>messageBox</code></p>
<pre><code class="language-js">var messageBox = document.createElement("div");
messageBox.className = "messageBox";
messageBox.style = messageBox_style;
</code></pre>
<p>2、创建 <code>header</code></p>
<pre><code class="language-js">//创建 header
var header = document.createElement("div");
header.className = "messageBox_header";
header.style = header_style;
var headerText = document.createElement("div");
headerText.textContent = "提示";
var headerBtn = document.createElement("div");
headerBtn.style = "cursor:pointer;text-align:right;";
headerBtn.textContent = "x";
headerBtn.onclick = function () {
mainFrameSetParent.removeChild(messageBoxWrap);
enableKeyboard();
};
</code></pre>
<p>当点击头部的关闭按钮时,在顶层文档对象(<code>mainFrameSetParent</code>)中移除弹框。这里 <code>enableKeyboard</code><br>
表示移除弹框后恢复键盘事件。因为有时候业务操作飞快,有时候因为电脑卡,弹框还没完全关闭,使用键盘操作去到了其他页面,导致弹框显示在了其他页面。</p>
<p>3、创建 <code>content</code> 包裹层</p>
<pre><code class="language-js">//创建 content 包裹层
var contentBox = document.createElement("div");
contentBox.className = "messageBox_content";
contentBox.style = content_style;
contentBox.textContent = paramString;
</code></pre>
<p>4、创建 <code>footer</code></p>
<p>这里如果使 <code>confirm</code> 框,则多一个取消按钮</p>
<pre><code class="language-js">//创建 footer
var footer = document.createElement("div");
footer.className = "messageBox_footer";
footer.style = footer_style;
var yesBtn = document.createElement("button");
yesBtn.style = button_style + button_primary;
yesBtn.textContent = type === "confirm" ? "确认" : "确定";
yesBtn.onclick = function () {
if (type === "alert") {
    if (currentAlertBoxCount &gt; 0) {
      currentAlertBoxCount--;
    }
}
resolve(true);
mainFrameSetParent.removeChild(messageBoxWrap);
enableKeyboard(); // 关闭弹框后恢复键盘事件
};
if (type === "confirm") {
var noBtn = document.createElement("button");
noBtn.style =
    button_style + "margin-left: 10px;border-radius: 20px 20px;";
noBtn.textContent = "取消";
noBtn.onclick = function () {
    resolve(false);
    mainFrameSetParent.removeChild(messageBoxWrap);
    enableKeyboard(); // 关闭弹框后恢复键盘事件
};
}
footer.appendChild(yesBtn);
if (type === "confirm") {
footer.appendChild(noBtn);
}
</code></pre>
<p>5、将创建的弹框插入顶层文档</p>
<p>创建弹框时,使焦点聚焦到弹框,并且禁用键盘事件。</p>
<pre><code class="language-js">messageBox.appendChild(header);
messageBox.appendChild(contentBox);
messageBox.appendChild(footer);
messageBoxWrap.appendChild(messageBox);
//将创建好的弹框插入顶层 document
mainFrameSetParent.appendChild(messageBoxWrap);
messageBoxWrap.focus();
disableKeyboard();
</code></pre>
<p>6、页面调用弹出框</p>
<p>设置 <code>currentAlertBoxCount</code> 代表 <code>alert</code> 框的数量,避免同时出现多个弹框</p>
<pre><code class="language-js">var currentAlertBoxCount = 0;
async function modernConfirm(str) {
return await showMessagebox("confirm", str);
}
async function modernAlert(str) {
if(currentAlertBoxCount&gt;0){
    return
}
currentAlertBoxCount++;
return await showMessagebox("alert", str);
}
</code></pre>
<h4 id="完整代码">完整代码</h4>
<pre><code class="language-js">/*弹框的默认样式;*/
var messageBoxWrap_class = "modernMessagebox";
var messageBoxWrap_style =
"width:100%;height:100%;position:fixed;top:0;left:0;text-align:center;";
var messageBox_style =
"user-select:none;display: inline-block;width: 420px;padding: 10px 0px 20px;vertical-align: middle;background-color: #fff;border-radius: 4px;border: 1px solid #ebeef5;font-size:18px;box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);text-align: left;";
var header_style =
"padding: 10px 16px 10px;font-size:14px;display:flex;justify-content: space-between;";
var content_style = "padding: 10px 15px;color: #606266;font-size: 14px;";
var footer_style = "padding: 5px 15px 0;text-align: right;";
var button_style =
"display: inline-block;line-height: 1;wite-space: nowrap;cursor: pointer;background: #fff;border: 1px solid #dcdfe6;color: #606266;-webkit-appearance: none;text-align:center;box-sizing:border-box;outline:0;margin:0;transition:.1s;font-weight:500;padding:10px 16px;font-size:12px;border-radius:3px;";
var button_primary =
"color: #fff;background: rgb(11, 87, 208);border: 1px solid rgb(11, 87, 208);border-radius: 20px 20px;";
var currentAlertBoxCount = 0;
//弹框时禁用键盘事件,弹框消失后启用键盘事件,防止弹框还未消失,使用 tab+enter去了其他页面的情况
let keyboardDisabled = false;
function disableKeyboard() {
keyboardDisabled = true;
document.addEventListener("keydown", handleKeyDown);
}
function enableKeyboard() {
keyboardDisabled = false;
document.removeEventListener("keydown", handleKeyDown);
}
function handleKeyDown(event) {
if (keyboardDisabled) {
    event.preventDefau1t();
}
}
// type 区分是 alert 还是 confirm
// paramSting 表示提示框的内容,项目中没有自定义标题的需求,所以这里提示框都用统一的标题
function showMessagebox(type, paramString) {
//获取项目顶层的document,弹框显示需要覆盖顶层页面
var topDoc = window.top.document;
var mainFrameSet = topDoc.querySelector("#setMain");
var mainFrameSetParent = mainFrameSet.parentNode;
var topDocBody = window.top.document.body;
//创建弹框盒子,添加遮罩层
return new Promise((resolve, reject) =&gt; {
    var messageBoxWrap = document.createElement("div");
    messageBoxWrap.setAttribute("tabindex", "-1");
    messageBoxWrap.className = messageBoxWrap_class + Date.now();
    messageBoxWrap.style = messageBoxWrap_style + ";width:" + topDocBody.clientWidth + "px;";
    var messageBox = document.createElement("div");
    messageBox.className = "messageBox";
    messageBox.style = messageBox_style;
    //创建 header
    var header = document.createElement("div");
    header.className = "messageBox_header";
    header.style = header_style;
    var headerText = document.createElement("div");
    headerText.textContent = "提示";
    var headerBtn = document.createElement("div");
    headerBtn.style = "cursor:pointer;text-align:right;";
    headerBtn.textContent = "x";
    headerBtn.onclick = function () {
      mainFrameSetParent.removeChild(messageBoxWrap);
      enableKeyboard();
    };
    header.appendChild(headerText);
    header.appendChild(headerBtn);
    //创建 content 包裹层
    var contentBox = document.createElement("div");
    contentBox.className = "messageBox_content";
    contentBox.style = content_style;
    contentBox.textContent = paramString;
    //创建 footer
    var footer = document.createElement("div");
    footer.className = "messageBox_footer";
    footer.style = footer_style;
    var yesBtn = document.createElement("button");
    yesBtn.style = button_style + button_primary;
    yesBtn.textContent = type === "confirm" ? "确认" : "确定";
    yesBtn.onclick = function () {
      if (type === "alert") {
      if (currentAlertBoxCount &gt; 0) {
          currentAlertBoxCount--;
      }
      }
      resolve(true);
      mainFrameSetParent.removeChild(messageBoxWrap);
      enableKeyboard();
    };
    if (type === "confirm") {
      var noBtn = document.createElement("button");
      noBtn.style =
      button_style + "margin-left: 10px;border-radius: 20px 20px;";
      noBtn.textContent = "取消";
      noBtn.onclick = function () {
      resolve(false);
      mainFrameSetParent.removeChild(messageBoxWrap);
      enableKeyboard();
      };
    }
    footer.appendChild(yesBtn);
    if (type === "confirm") {
      footer.appendChild(noBtn);
    }

    messageBox.appendChild(header);
    messageBox.appendChild(contentBox);
    messageBox.appendChild(footer);
    messageBoxWrap.appendChild(messageBox);
    //将创建好的弹框插入顶层 document
    mainFrameSetParent.appendChild(messageBoxWrap);
    messageBoxWrap.focus();
    disableKeyboard();
});
}
async function modernConfirm(str) {
return await showMessagebox("confirm", str);
}
async function modernAlert(str) {
if(currentAlertBoxCount&gt;0){
    return
}
currentAlertBoxCount++;
return await showMessagebox("alert", str);
}
</code></pre><br><br>
来源:https://www.cnblogs.com/zsxblog/p/18929807
頁: [1]
查看完整版本: 改造jsp项目的alert框和confirm框