必须用form.on('select(filtername)')监听,因layui隐藏原生select并用div+ul模拟下拉,原生change事件无效;需确保select在layui-form容器内、有lay-filter属性,动态更新选项后必须调form.render('select', 'filtername')。

必须用 form.on('select(filterName)'),原生 change 事件无效
layui 渲染 select 后会隐藏原生 <select></select> 元素,用 div + ul 模拟下拉面板,所有交互都由 layui 内部接管。直接写 $('select').on('change', ...) 或 elem.addEventListener('change', ...) 基本监听不到——因为原生元素没被真正触发。
唯一可靠方式是使用 layui 的 form 模块提供的事件绑定:
-
lay-filter属性必须存在且与form.on('select(xxx)')中的xxx完全一致 -
<select></select>必须包裹在class="layui-form"的容器内(<form></form>或<div> 都行) <li>如果 select 是 AJAX 加载、弹窗中动态插入的,需在 DOM 挂载后立即调用 <code>form.render('select') -
data.value:当前选中的<option></option>的value属性值(字符串),直接用它 -
data.elem:原生<select></select>DOM 元素,但它的.value始终为空或旧值,不要读取 -
data.othis:渲染后的美化下拉框 DOM(那个带箭头的盒子),可用于样式操作,不用于取值 - 替换完
<option></option>后,立刻执行form.render('select', 'targetFilter')(推荐指定 filter,避免全局重绘) - 如果目标 select 没设
lay-filter,就用form.render('select')全局刷新,但性能稍差 - 不要指望“等用户点一下再触发”,首次点击可能就失效;render 是强制同步 UI 和内部状态的必要步骤
- 先调
form.val('filterName', { 'nameAttr': 'targetValue' }),其中nameAttr是 select 的name属性值 - 再紧跟着调
form.render('select', 'filterName'),否则监听器不会响应 - 如果表单里有多个 select,建议始终传第二个参数(filter 名),避免误刷其他下拉框
data.value 是唯一可信的选中值,别碰 data.elem.value
在 form.on('select(filterName)', function(data) { ... }) 回调里,data 是 layui 封装的对象,不是原生 Event。它有三个关键字段:
错误写法:$(data.elem).val()、data.elem.value、this.value —— 这些都不可靠,尤其在动态更新选项后大概率返回空字符串。
动态更新下拉选项后,必须调用 form.render('select')
常见场景:第一个 select 选中后,用 AJAX 拉第二个 select 的 <option></option>,然后用 html() 替换内容。此时新插入的选项只是纯 HTML,layui 并未识别,点击不会触发 form.on('select'),也无法正确读取 data.value。
解决办法很明确:
想手动设置值并触发监听?只能走 form.val() + form.render('select')
比如页面初始化时要默认选中某项,或根据其他操作联动设置值,又希望自动触发 form.on('select') —— 不能用 $('select').val('xxx').trigger('change'),也不能用 dispatchEvent,这些对 layui 渲染后的结构完全无效。
正确链路只有一条:
漏掉 form.render('select') 是最常被忽略的一步,也是为什么“设置了值但监听函数没执行”的根本原因。











