拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

开屏弹窗的制作

开屏弹窗的制作

前言

很多网站、H5 活动页面会有进入页面自动弹出提示弹窗的需求,弹窗附带【今日不再提示】复选框,勾选关闭后,当天再次刷新页面不会重复弹出;但是打开新标签页依然可以弹窗,这里就需要区分localStorage和sessionStorage的存储特性。

本文原生 JS 实现,不使用任何框架,包含:自动判断弹窗是否展示、文本动态渲染、复选框控制 “今日不再提示”、两种本地存储的配合使用,适合前端新手学习本地存储、弹窗交互逻辑。

实现效果

页面加载完成,自动判断是否展示弹窗:

  1. 满足条件 → 弹窗显示;不满足 → 弹窗隐藏
  2. 弹窗内展示标题 + 文本内容,复选框【今日不再提示】
  3. 勾选复选框点关闭:记录时间戳,今天内再次打开页面不再弹出,第二天自动恢复弹窗
  4. 不勾选复选框点关闭:仅当前标签页本次会话不再弹出,新开标签页依旧会弹出弹窗

知识点:localStorage永久存储(手动删缓存才消失,我们用时间戳控制有效期);sessionStorage仅当前标签会话有效,关闭标签页就清空。

完整源码

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>原生JS 开屏弹窗 今日不再提示</title> <style> body { margin: 0; padding: 0; font-family: 'Microsoft YaHei', sans-serif; background-color: #f9f9f9; display: flex; justify-content: center; align-items: center; height: 100vh; } #box { display: none; /* 默认设置不显示 */ width: 320px; padding: 20px; background-color: white; border-radius: 12px; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.1); position: relative; } .title { color: #e74c3c; font-size: 1.5em; margin-bottom: 15px; font-weight: bold; display: flex; justify-content: center; align-items: center; } #content { font-size: 14px; line-height: 1.6; color: #333; margin-bottom: 15px; padding: 10px; background-color: #f8f9fa; border-radius: 8px; } .checkbox-container { display: flex; align-items: center; justify-content: flex-end; margin-bottom: 15px; font-size: 12px; color: #666; } .checkbox-container input { margin-right: 5px; } .btn { background-color: #8e44ad; color: white; border: none; padding: 10px 20px; font-size: 16px; border-radius: 8px; cursor: pointer; transition: background-color 0.3s; display: block; margin: 0 auto; } .btn:hover { background-color: #9b59b6; } </style> </head> <body> <div id="box"> <div class="title">圣诞快乐</div> <div id="content"></div> <div class="checkbox-container"> <input type="checkbox" id="dontShowAgain" />今日不再提示 </div> <button class="btn" onclick="breakAlert()">关闭</button> </div> <script> let content = document.getElementById('content'); //获取content 的div let obj = { contents: '《救勒歌》是南北朝时期流传于北朝的乐府民歌,一般认为是由鲜卑语译成汉语的诗作。此诗歌咏了北国草原壮丽富饶的风光,抒写救勒人热爱家乡热爱生活的豪情。开头两句交代救勒川位于高耸云宵的阴山脚下,将草原的背景衬托得十分雄伟。接着两句用“穹庐”作比喻,说天空如蒙古包,盖住了草原的四面八方,以此来形容极目远望,天野相接,无比壮阔的景象。最后三句描绘了一幅水草丰盛、牛羊肥壮的草原全景图。有静有动,有形象,有色彩。全诗风格明朗豪爽,境界开阔,音调雄壮,语言明白如话,艺术概括力极强,受到历代文论家和文学史论著的好评。对它的学术研究,经久不衰。' }; //要添加的对象内容 content.innerHTML = obj.contents; //将对象内容添加到content div中 实现动态渲染 //判断是否需要显示弹窗函数 let box = document.getElementById('box'); function shouldShowAlert() { let storedTime = localStorage.getItem('times'); let currentTime = new Date().getTime(); if ((storedTime && storedTime > currentTime) || sessionStorage.getItem('status') == 1) { return false; //返回给调用函数结果false } return true; } //if调用shouldShowAlert()函数,判断是否显示弹窗 if (shouldShowAlert()) { box.style.display = 'block'; } //定义弹窗关闭函数 let dontShowAgain = document.getElementById('dontShowAgain'); //获取dontShowAgain checkbox function breakAlert() { //带有今日不再提示的函数 if (dontShowAgain.checked) { let tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); localStorage.setItem('times', tomorrow.getTime()); } else { localStorage.removeItem('times'); } sessionStorage.setItem('status', '1'); box.style.display = 'none'; } </script> </body> </html>

核心逻辑拆解

1. DOM 与样式

  • 弹窗容器#box,默认display:none隐藏;满足条件才改成block展示。
  • #content用来动态渲染文本内容,文本放在 JS 对象里,使用innerHTML渲染,方便后端或者配置修改文案。
  • 复选框dontShowAgain,用来标记用户是否勾选【今日不再提示】。

2. 本地存储区别(重点!面试常问)

表格

存储生命周期作用域本项目用途
localStorage永久保存,需要手动清除同源所有标签页共享保存明天 0 点的时间戳,实现今日不再弹出
sessionStorage当前标签会话,关闭标签页自动清空仅限当前标签页标记本次打开页面已经关闭弹窗,刷新当前页不再弹,新开标签页不受影响

核心逻辑: 勾选关闭弹窗 → 存入 localStorage:明天的时间戳。下次页面加载,拿当前时间对比,如果当前时间小于存储的时间戳,代表还没到第二天,不弹窗。 无论勾不勾选,都会往 sessionStorage 存入 status=1,当前标签页刷新不会再次弹窗。

3. 弹窗判断函数shouldShowAlert()

function shouldShowAlert() { let storedTime = localStorage.getItem('times'); let currentTime = new Date().getTime(); // 两种情况不弹窗:①存储的过期时间>当前时间(今日已禁用弹窗)②session标记本次会话关闭过弹窗 if ((storedTime && storedTime > currentTime) || sessionStorage.getItem('status') == 1) { return false; } return true; }

页面加载直接调用,如果返回 true,弹窗display:block显示。

4. 关闭弹窗函数 breakAlert ()

function breakAlert() { if (dontShowAgain.checked) { // 获取明天此刻的时间戳存入localStorage let tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); localStorage.setItem('times', tomorrow.getTime()); } else { // 不勾选,则删除localStorage的时间记录 localStorage.removeItem('times'); } // 标记当前会话弹窗已关闭 sessionStorage.setItem('status', '1'); box.style.display = 'none'; }

现有代码存在的缺陷 & 优化方案

缺陷 1:时间是 “24 小时制”,不是自然日 0 点

当前代码:tomorrow.setDate(tomorrow.getDate() + 1),是24 小时后失效。

举例:晚上 22 点关闭弹窗,会到明天 22 点才恢复弹窗,不是第二天 0 点。 ✅优化方案:把时间设置为次日凌晨 0 点,实现真正自然日。

let tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); tomorrow.setHours(0,0,0,0); // 设置为凌晨零点

缺陷 2:弹窗没有遮罩层

现在弹窗直接居中,页面底层内容还能点击。正式项目建议增加黑色半透明遮罩,防止底层交互。

缺陷 3:innerHTML 存在 XSS 风险

当前用innerHTML渲染文本,如果文案来源是后端接口,不要直接使用 innerHTML,优先使用innerText。

缺陷 4:没有做版本 / 缓存清理

如果业务更新弹窗内容,老用户本地缓存还存在,看不到新弹窗。可以增加版本号校验,版本不一致时清空存储强制弹窗。

拓展业务场景

  1. 活动公告弹窗、协议提示、活动规则弹窗
  2. 每日签到提示、每日欢迎提示
  3. 小程序 / H5 的开屏公告(web 端同源存储逻辑通用)

知识点总结

  1. localStorage.setItem/getItem/removeItem永久本地存储,以时间戳实现有效期。
  2. sessionStorage会话存储,标签关闭自动消失。
  3. 页面初始化自动执行判断逻辑,控制弹窗显示隐藏。
  4. JS Date 时间对象,通过时间戳对比来做定时过期功能。
  5. innerHTML 动态渲染页面内容,适合文案配置化。

注意:存储都属于前端本地存储,清除浏览器缓存后,记录会丢失。重要业务逻辑不能依赖前端存储,只能做体验优化。

返回列表