根本原因是Layui将原生select隐藏(display:none),交互落在生成的.layui-form-select容器上;应操作该容器并确保form.render('select')已执行,或改源码用touchstart兼容移动端。

为什么 click 绑定在原生 <select> 上完全无效
因为 Layui 渲染后会把原始 <select> 隐藏(display: none),所有交互都落在它生成的 <div class="layui-form-select"> 上。你对原生 select 元素调用 .click() 或绑定 $(select).on('click'),等于点空气——DOM 存在但不可见、无事件响应区。
常见错误现象:
-
$('#mySelect').click()没反应,控制台也没报错 - 手动点击下拉箭头能展开,但 JS 触发就失败
- 动态插入的
select即使加了lay-filter,form.on('select(xxx)')也不触发
正确触发方式:必须操作 .layui-form-select 容器
要模拟用户点击行为,目标必须是 Layui 生成的浮层容器,不是原始 select。关键前提是:该容器已存在(即 form.render('select') 已执行)。
- 展开指定下拉:
$('.layui-form-select[lay-filter="city"]').trigger('click')或.click() - 确保渲染完成:动态添加后立刻执行
form.render('select'),再操作 DOM - 如果用
layer.open弹窗,要在success回调里先layui.use('form'),再form.render('select') - 老版本(Layui < 2.7)不支持
form.select.open(),硬触发是唯一可靠路径
form.on('select(xxx)') 失效的三大硬伤
这个监听器依赖两个前提:一是 select 有唯一 lay-filter,二是渲染时没被重复包裹或样式干扰。失效往往不是代码写错,而是结构或样式“悄悄破坏”了渲染链路。
-
layui-form容器缺失:动态添加的select必须放在带class="layui-form"的父元素内,不能只给select加类 -
.layui-form select的display: none被覆盖:其他 CSS 把原生select显式设为block或inline,导致 Layui 渲染逻辑错乱,出现双下拉、事件只绑在旧节点上 - 多个
select共用同一个lay-filter值:Layui 认为它们是同一组件,第二次form.render('select')可能跳过或覆盖前一次绑定
移动端点不动?别改 HTML,直接修事件源
根本问题不是“不兼容”,而是 Layui 1.x 默认用 click 绑定 .layui-form-select,而 iOS/Android 对绝对定位浮层里的 click 响应极不稳定——常表现为点一下没反应、点两下才弹出、或只在边框边缘生效。
- 定位到
layui.js中select.on('click', '.layui-form-select'这一行(约 6800 行,版本不同略有偏移) - 改成
select.on('touchstart', '.layui-form-select',并在回调第一行加e.preventDefault() - 保留原有
click绑定不变,实现 PC + 移动双事件共存 - 改完必须清浏览器缓存,否则 JS 仍走旧逻辑
这个改动最小、效果最稳,比换组件或强行 hack CSS 更贴近问题本质。真正容易被忽略的是:事件监听器一旦绑定,就不会随 DOM 重建自动更新——所以动态内容必须重新绑定,或统一委托到 document。


















