Layui layer 弹层实战:layer.open 配置、关闭方法与高频坑点速查
【免费下载链接】layui一套遵循浏览器原生态开发模式的 Web UI 组件库。项目地址: https://gitcode.com/GitHub_Trending/la/layui
页面弹层一多就开始打架:遮罩叠了三四层、关掉一个弹层把别的也带走了、loading 转完圈却忘了关。这些问题的根源通常是没吃透 layer 的 index 机制和几种内置类型。layer 是 layui 内置的通用弹出层组件,原生 JavaScript 实现、不依赖 jQuery,alert/confirm/msg/load/tips 这些快捷方法覆盖了绝大多数弹窗场景,下面按"先跑通、再套场景、最后排坑"的顺序讲。
一、能力速览
| 能力点 | 一句话说明 | 典型适用场景 |
|---|---|---|
| 五种原生类型 | type 0~4 对应 dialog / page / iframe / loading / tips,一套 API 全覆盖 | 提示框、弹窗页面、内嵌页面、等待转圈、元素旁气泡 |
| 快捷方法 | alert / confirm / msg / load / tips / prompt 开箱即用 | 确认删除、操作结果反馈、口令输入 |
| index 管理 | 每次 open 返回唯一 index,close/closeLast/closeAll 精确控制 | 异步请求中关闭指定 loading |
| 动画与方位 | anim 数字或 slide 方向、offset 九宫格定位 | 底部抽屉、从右侧滑入的面板 |
| 主题覆写 | skin 传入任意 class,叠加自定义样式即可换肤 | 品牌色弹窗、特殊业务皮肤 |
五种类型在源码里写得很直白:type: ['dialog', 'page', 'iframe', 'loading', 'tips'],type 数字就是数组下标,记不住就翻 源码 开头这几行。
二、三步跑通第一个 layer
第一步:引入 layui
一个 html 文件引入样式和脚本即可,layer 随主包加载,无需单独引 layer.js。这段代码只做资源引入:
<!doctype html> <html> <head> <meta charset="utf-8" /> <title>layer 弹层入门</title> <link rel="stylesheet" href="layui.css" /> </head> <body> <button id="btn">弹出提示</button> <script src="layui.js"></script>第二步:弹出第一个 msg
layer.msg 是最常用的轻提示,默认 3 秒自动消失、无遮罩,适合"操作成功"这类反馈。下面这行就是官方演示页里的第一句代码:
layui.use(() => { var layer = layui.layer; document.getElementById('btn').onclick = function () { // 返回 index,需要手动关闭时用它 var index = layer.msg('保存成功'); }; });第三步:带按钮的 confirm 与手动关闭
confirm 弹确认框,点击确定才会执行回调,回调里用 index 关掉弹层,这就是 layer 最核心的"开-关"闭环。
layer.confirm('确定要删除这条数据吗?', function (index) { // 确定回调:先干正事,再关弹层 layer.close(index); // 注释:忘记 close,弹层会一直挂着 }); // 自定义页面层:type 1 + area 定宽高,yes 是确定按钮回调 var idx = layer.open({ type: 1, title: '编辑信息', area: ['420px', 'auto'], content: '<div style="padding:20px">这里放你的表单</div>', btn: ['保存', '取消'], yes: function (i) { layer.close(i); }, });跑通后你应该看到:点按钮出现一条居中的小提示,两秒左右自动淡出;confirm 弹出一个带"确定/取消"的对话框,点确定后弹层关闭、遮罩消失。
三、场景驱动的配置技巧
登录页"忘记密码"弹窗
痛点:确认框只能显示文本,要用户输入一次验证码就得自己拼输入框。layer.prompt 是内置的输入型弹层,formType 1 是密码框,不用手写 input。
// 弹出口令输入框,formType: 1 渲染为密码输入 layer.prompt({ title: '重置密码,请输入当前密码', formType: 1 }, (pass, index) => { fetch('/api/reset', { method: 'POST', body: JSON.stringify({ pwd: pass }), }).then(() => { layer.close(index); // 注释:无论成败都要关,失败再弹 msg layer.msg('重置成功', { icon: 1 }); }); });- formType:0 文本 / 1 密码 / 2 多行文本,决定输入框形态
- 回调第二个参数就是index,关闭时直接用它
- 弹窗样式想统一,可以传
**title**或外层skin覆写
异步请求的 loading 遮罩
痛点:请求耗时两秒以上,页面无反馈,用户会连点三次。layer.load 弹转圈层,关键点是用它返回的 index 精确关闭,而不是 closeAll。
var loadIndex = layer.load(1, { shade: [0.1, '#fff'], // 注释:浅色遮罩,用户还能看到页面 }); fetch('/api/list') .then(r => r.json()) .then(data => { layer.close(loadIndex); // 注释:必须用 open 时拿到的 index layer.msg('已加载 ' + data.length + ' 条'); });- load(icon, options):icon 0/1 是两种转圈,2 是风格 2
- shade传数组
[透明度, 背景色]可自定义遮罩 - 回调里忘了 close 是最常见事故,可加
.catch兜底关闭
商品列表的图片查看器
痛点:缩略图列表点一张,要能放大、左右切换,自己写全屏预览很费劲。layer.photos 直接吃一个列表选择器,自动接管查看器。
<ul id="goods"> <li><img src="a.jpg" alt="商品1" /></li> <li><img src="b.jpg" alt="商品2" /></li> </ul>layer.photos({ photos: '#goods', // 注释:选择器直接指向缩略图容器,src 自动取 img hideFooter: true, // 隐藏底部操作栏,界面更干净 });- photos可以传选择器,也可以传
{ data: [...] }对象,两种都认 - 点击缩略图即全屏预览,hideFooter控制底部栏显隐
四、高频坑点与调优
坑一:closeAll 一关关所有
你大概率遇到过:关了 loading 之后,本来还开着的业务弹层也被带走了。原因是closeAll()不带参数会清掉全部类型,而 loading 和页面层经常同时存在。
// 错误写法:连业务弹层一起关了 layer.closeAll(); // 正确:只清 loading 类型,其他弹层不受影响 layer.closeAll('loading');坑二:异步里忘传 index,弹层挂死
你大概率遇到过:转圈转到页面刷新还没停。原因是回调闭包里忘了 index,或用了layer.close()这种不存在的调用。
var loadIndex = layer.load(); ajax('/api/save', { success: () => layer.close(loadIndex), error: () => layer.close(loadIndex), // 注释:失败分支同样要关 });坑三:同 id 重复 open 不会返回 index
你大概率遇到过:想用 id 防重复弹出,结果第二次点击拿不到 index,后续 close 失败。源码逻辑是:同 id 的弹层已存在时,直接显示旧弹层并return,不再返回新 index。
// 复用场景:拿到已有弹层的 index 再操作 var layero = $('.lay-layer #my-form').closest('.lay-layer'); var index = layero.attr('times'); // times 属性存的就是 index- 性能调优:iframe 层(type 2)配合
id+hideOnClose: true,关闭时只隐藏不销毁,二次打开不用重新加载页面 - 性能调优:弹层多时把
minStack设为 false,避免最小化窗口在左下角越堆越多 - 性能调优:能用
layer.msg就别开layer.open,msg 默认无遮罩无标题,DOM 开销小得多
五、主题定制与生态集成
自定义主题
给 open 传skin: 'my-skin',再覆写几个核心 class 就能换肤。容器主 class 是lay-layer(不是网上老文章的layui-layer),这是 v3 源码里的实际命名。
.lay-layer-my-skin { border-radius: 10px; box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2); } .lay-layer-my-skin .lay-layer-title { color: #fff; background: linear-gradient(135deg, #667eea, #764ba2); border-radius: 10px 10px 0 0; }覆写样式建议放在 src/css/modules/layer.css 同级之后引入,保证优先级生效。
与 datePicker 组件集成
弹层内的组件要在success回调里初始化,此时 DOM 已经挂载。以 datePicker 为例:
layer.open({ type: 1, title: '选择日期', area: ['300px', 'auto'], content: '<input id="dp" class="layui-input" />', success: function () { // 注释:必须在 success 里 render,此时弹层 DOM 已就位 layui.datePicker.render({ elem: '#dp', done: (d, i) => { layer.close(i); console.log('选中:', d.value); }, }); }, });datePicker 的渲染参数与用法可对照 src/components/datePicker.js 及演示页 tests/visual/datePicker.html。
六、速查卡
| API / 配置项 | 作用 | 典型值 |
|---|---|---|
layer.open(options) | 通用弹层,返回 index | options 见下 |
type | 弹层类型:0 对话 / 1 页面 / 2 iframe / 3 加载 / 4 提示 | 1 |
area | 宽高 | ['420px', 'auto'] |
offset | 方位:auto 居中 / t / r / b / l / lt / lb / rt / rb | 'b' |
anim | 动画:0~6 数字或 slide 方向 | 4、'slideUp' |
shade | 遮罩:数字透明度或数组 | [0.1, '#fff'] |
time | 自动关闭毫秒数,0 为不关 | 3000 |
layer.close(index)/closeLast/closeAll(type) | 关闭指定 / 最近 / 某类型全部弹层 | closeAll('loading') |
官方演示页见 tests/visual/layer.html,核心源码见 src/components/layer.js,配置默认值集中在文件内Class.pt.config一段,查参数行为时直接看那里最快。
【免费下载链接】layui一套遵循浏览器原生态开发模式的 Web UI 组件库。项目地址: https://gitcode.com/GitHub_Trending/la/layui
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考