layui中监听select必须用form.on('select(filter)', callback),filter值需与lay-filter属性完全一致,且select须在layui-form容器内;动态插入需先form.render('select');联动时须清空、禁用下级select,加载后render并确保lay-filter唯一。

form.on('select(filter)') 是唯一有效监听方式
原生 change 事件在 layui 中完全失效——因为 layui 把原始 <select></select> 隐藏了,替换成 div+ul+li 的模拟结构,所有交互都走内部逻辑。你绑 addEventListener('change') 或 $.on('change'),根本收不到任何信号。
必须用 layui 自带的监听机制:form.on('select(xxx)', callback),其中 xxx 必须和 <select lay-filter="xxx"></select> 的值**完全一致**。
-
<select name="province" lay-filter="area"></select>→ 监听写法必须是form.on('select(area)', ...) - select 必须包裹在
class="layui-form"的容器内,否则 form 模块不接管,监听直接不注册 - 如果 select 是 JS 动态插入(比如 ajax 后
append()进来的),得先调form.render('select'),否则form.on根本不会生效
联动时清空下级 + 重载选项 + 必须 render
监听到 change 后,不能只发请求、填 option 就完事。漏掉关键步骤会导致“看着有选项,点不动”“选了没反应”“提交值为空”等现象。
- 每次加载下一级前,先清空 DOM:
$('#city').empty().append('<option value="">请选择城市</option>') - 禁用下级 select 防误操作:
$('#city').prop('disabled', true) - 请求成功后,填完新
option,**立刻**执行form.render('select');若页面有多个表单,推荐传第二个参数:form.render('select', 'yourFormFilter') - 别用
$('#city').val('xxx').trigger('change')模拟触发——这不会通知 layui 内部状态,后续联动全断
动态插入的 select 容器,监听容易失效
如果「城市」select 是在「省份」请求成功后才创建并 append() 到页面的,而你在页面加载时就写了 form.on('select(city)', ...),那这个监听器压根不会绑定上——元素还不存在。
两个靠谱解法:
- 把监听代码挪到省份请求成功的回调末尾,确保 DOM 已存在再注册:
form.on('select(city)', ...) - 改用原生事件委托:给父容器(如
form.layui-form)监听change,再用event.target.name === 'city'判断,绕过 layui 的注册时机限制
另外注意:重复调用 form.render('select') 可能导致已绑定的事件被覆盖,尤其是多级联动中频繁渲染时。
联动后如何让下级 select 正确响应 change?
很多人卡在“省选完了,市也刷出来了,但点市没反应”。核心问题不是数据没加载,而是**下级 select 缺少 lay-filter 属性或值不匹配**。
- 每个参与联动的 select 都必须有
lay-filter,且值全局唯一(比如lay-filter="province"、lay-filter="city") - 不要复用同一个
lay-filter值监听多个 select,layui 不支持一对多监听 - 如果用了
lay-search,注意它会劫持输入框焦点,某些版本中form.on('select(xxx)')在搜索状态下不触发——建议前三级不用lay-search,仅最后一级开启
最易忽略的是:联动后没同步 disabled 状态。上级变更时,下级要设为 disabled=true,等数据加载完成再 disabled=false 并 form.render('select'),否则用户可能点出脏数据。











