layui原生form.on('select(filter)')不支持多选监听,仅响应单选且返回字符串data.value;多选必须用formselects插件或transfer组件,前者通过formselects.on()回调获取value数组,后者监听transfer.on('change')事件获取value字段数组。
layui 原生 form.on('select(filter)') **不支持多选状态监听**——它只响应单选变化,且只返回 data.value(字符串),无法获取多个选中值。真要监听多选行为,必须换方案。
为什么原生 form.on('select') 对多选无效
layui 的 form.on('select(xxx)') 内部监听的是美化后下拉框的点击事件,触发逻辑基于「单次选中替换」,不感知 checkbox 状态切换。当你给 <select multiple></select> 加上 lay-filter,它会被 layui 渲染成普通单选样式(甚至渲染失败),form.on 回调根本不会触发。
- 浏览器原生
<select multiple></select>在 layui 中会丢失美化样式,退化为丑陋的滚动列表 -
form.render('select')不处理multiple属性,渲染后仍无交互增强 - 即使强行监听原生
change事件,event.target.value只返回第一个选中项,不是数组
用 layui-formSelects 插件监听多选变化
这是目前最稳定、社区验证过的方案。它把多选封装成独立组件,提供明确的 change 回调,返回完整选中值数组。
- 引入插件:下载
formSelects-v4.js和对应 CSS,确保在layui.use之前加载 - HTML 中用隐藏的
<select></select>定义数据源,不加lay-filter,也不包裹在layui-form里 - 初始化时传入
searchKey、filterable等参数,关键是要设置trigger: 'change' - 监听用
formSelects.on('filterName', function(id, arr){ ... }),其中arr是选中项的 value 数组
示例:
<select id="myMulti" multiple lay-ignore><option value="1">Java</option> <option value="2">Python</option> <option value="3">Go</option></select>
JS 初始化后:
formSelects.on('myFilter', function(id, arr){
console.log('当前选中:', arr); // ['1', '3']
console.log('选中数量:', arr.length);
});
动态更新多选项后必须重新绑定监听
如果用 AJAX 拉取新选项并调用 formSelects.data('myFilter', 'server', ...) 更新数据,旧的监听函数不会自动继承到新 DOM 上——formSelects.on 是一次性绑定,不是事件委托。
- 每次调用
formSelects.data()后,需再次执行formSelects.on('myFilter', ...) - 或者改用闭包方式,在初始化时就定义好回调函数,避免重复声明
- 别依赖
form.render(),它对 formSelects 无效;这个插件有自己的渲染和重载机制
Transfer 组件替代方案的监听要点
如果项目已用 layui 的 transfer 模块做左右穿梭,它的状态变化监听方式完全不同:
- 监听
transfer.on('change')事件,回调参数是对象{id: 'xxx', value: ['1','2']} -
value字段才是你真正需要的选中数组,不是data.value - 注意:transfer 的
id必须与 HTML 中lay-filter值一致,且初始化时不能漏掉parseData配置 - 若 transfer 数据来自远程,首次加载后需手动触发一次
transfer.render()才能激活 change 监听
多选状态的真实来源永远是插件自身的数据模型,不是 DOM 的 selected 属性——这点和原生 select 完全不同,容易误判。











