如何实现手机返回键按顺序逐个关闭Bootstrap模态框
逐次关闭Bootstrap模态框的实现方案
核心改造逻辑
- 新增数组作为模态框打开栈,按打开顺序存储激活的模态框元素
- 打开模态框时将当前模态框推入栈顶,同时新增一条独立的历史记录
- 触发返回操作时仅关闭栈顶的最上层模态框,弹出栈顶元素
- 新增标识位避免返回关闭模态框时触发连锁历史回退操作
完整实现代码
// 模态框存储栈,按打开顺序存储激活的模态框元素 var modalStack = []; // 标识是否是popstate触发的模态框关闭,避免循环触发历史回退 var isPopstateTriggered = false; var closedModalHashStateId = "#modalClosed"; var openModalHashStateId = "#modalOpen"; // 初始化hash状态 if (window.location.hash !== closedModalHashStateId) { window.location.hash = closedModalHashStateId; } function handleBackPress(event) { // 没有打开的模态框时正常走返回逻辑 if (modalStack.length === 0) return; event.preventDefault(); event.stopPropagation(); isPopstateTriggered = true; // 仅关闭栈顶的最上层模态框 const topModal = modalStack.pop(); $(topModal).modal('hide'); // 重置标识位 setTimeout(() => { isPopstateTriggered = false; }, 10); } // 绑定返回事件 $(window).on('popstate', handleBackPress); document.addEventListener("backbutton", handleBackPress, false); // 模态框打开时入栈 $('.modal').on('show.bs.modal', function(e) { // 避免同一个模态框重复入栈 if (!modalStack.includes(e.target)) { modalStack.push(e.target); } window.history.pushState('forward', null, './' + openModalHashStateId); }); // 模态框关闭时同步历史栈 $('.modal').on('hide.bs.modal', function(e) { // 如果是popstate触发的关闭,不需要再回退历史 if (isPopstateTriggered) return; // 如果当前关闭的是栈顶模态框,移除栈顶元素并回退历史 if (modalStack.length > 0 && modalStack[modalStack.length - 1] === e.target) { modalStack.pop(); window.history.back(); } else { // 非栈顶模态框被手动关闭时,从栈中移除对应元素 const index = modalStack.indexOf(e.target); if (index > -1) { modalStack.splice(index, 1); window.history.back(); } } });
功能说明
- 每次点击返回键仅关闭最上层的最后打开的模态框,下层模态框保留显示
- 手动点击模态框关闭按钮、点击蒙层关闭模态框时,会自动同步历史记录,不会出现历史栈错乱
- 所有模态框全部关闭后,点击返回键会正常触发页面返回逻辑,不影响原有页面跳转行为
内容的提问来源于stack exchange,提问作者Relaxing Music
相关产品推荐
相关产品推荐

