Layui 2.x 原生 select 不支持多选,需用 lay-select 容器+内嵌 checkbox 模拟:手动构建 dl 列表、监听点击、维护选中数组、同步标题文本,并通过隐藏域提交值。
layui 2.x 默认不支持多选下拉,得靠 lay-select + 自定义 DOM 模拟
layui 原生的 layui.form.select 只支持单选,没有 multiple 属性,直接写 <select multiple></select> 也不会被 layui 渲染成多选样式——它会忽略 multiple,只当普通下拉处理。
所以必须绕过原生渲染逻辑,用自定义 HTML + JS 行为模拟:保留 lay-select 的外观和交互基础,但把内部 <dl></dl> 列表项做成可勾选状态,并维护一个选中值数组。
常见错误现象:select 加了 multiple 却点不动选项;或点了没反馈、提交时拿不到多个值;或触发 change 事件但 this.value 仍是空字符串。
- 不要试图用
form.render('select')激活原生 multiple —— 它不生效 - 不要在
select上直接绑定click或change监听,layui 会接管并屏蔽原生行为 - 真实使用场景是:权限配置、标签筛选、多角色选择等需要显式勾选+回显的列表
用 lay-select 容器 + checkbox 手动构建多选项 DOM
核心思路是:让 layui 渲染一个“假下拉”,里面每个 <dd></dd> 内嵌一个 <input type="checkbox">,点击时阻止默认行为,手动 toggle 选中态并更新隐藏域或数据模型。
示例结构(关键部分):
<div class="layui-input-inline">
<select id="multiTag" lay-filter="multiTag" style="display:none">
<option value="">请选择标签</option>
<option value="1">前端</option>
<option value="2">后端</option>
<option value="3">运维</option>
</select>
<div class="layui-unselect layui-form-select" lay-key="multiTag">
<div class="layui-select-title">
<input type="text" placeholder="请选择标签" readonly="" class="layui-input">
<i class="layui-edge"></i>
</div>
<dl class="layui-anim layui-anim-upbit">
<dd lay-value=""><input type="checkbox" name="tag[]" value="" title="全部"></dd>
<dd lay-value="1"><input type="checkbox" name="tag[]" value="1" title="前端"></dd>
<dd lay-value="2"><input type="checkbox" name="tag[]" value="2" title="后端"></dd>
<dd lay-value="3"><input type="checkbox" name="tag[]" value="3" title="运维"></dd>
</dl>
</div>
</div>
注意:lay-key 必须唯一,否则多个组件会互相干扰;name 属性用于表单序列化时识别字段,但实际提交需靠 JS 收集勾选值。
-
lay-select容器本身不参与 form 提交,只是 UI 层,所有值必须由 JS 主动读取input[type=checkbox]:checked - 点击
<dd></dd>时要调用event.preventDefault(),否则 layui 会强制关闭下拉面板 - 兼容性上,layui 2.8.18 及以上对自定义
dl内容支持更稳,旧版本可能需手动调用form.render()补丁
监听勾选变化并同步显示文本(避免只改 DOM 不更新状态)
用户点了 checkbox,UI 要立刻反映已选内容,比如显示“前端 / 后端”或“已选 2 项”。但 layui 不知道你在 dl 里塞了 checkbox,所以必须自己监听、收集、刷新标题栏文本。
实操建议:
- 给每个
<dd></dd>绑定click事件(委托到.layui-form-select dl更稳妥) - 用
$(e.target).closest('dd').find('input:checked')获取当前选中项 - 拼接显示文本时注意:别直接用
val(),要读$(dd).attr('lay-value'),因为 checkbox 的value可能和下拉值不一致 - 更新标题输入框用
$('.layui-select-title .layui-input').val(text),别用val()写原生select,它不会响应 - 性能提示:频繁点击时避免重复触发
form.render(),它会导致重绘卡顿
提交前手动收集值并赋给隐藏域(否则后端收不到)
表单提交时,原生 select 元素仍为空,浏览器只会提交它自己的 value(永远是空字符串),所以必须把 checkbox 选中的值写进一个隐藏 <input>,名字和后端约定一致。
典型做法:
<input type="hidden" name="tags" id="tagsVal" value="">
然后在提交前执行:
var checkedVals = [];
$('.layui-form-select[lay-key="multiTag"] dd input:checked').each(function(){
checkedVals.push($(this).val());
});
$('#tagsVal').val(checkedVals.join(',')); // 或 JSON.stringify(checkedVals)
容易踩的坑:
- 忘记在
form.on('submit(...)')里加这一步,导致后端始终收不到多选值 - 用
serialize()提交时,如果没设置隐藏域,tags字段直接消失 - 后端接收类型要匹配:逗号分隔字符串 or 数组(取决于你传的是 join 还是 JSON)
- 移动端点击区域小,建议给
dd加padding: 8px 12px,别只依赖 checkbox 图标热区
最麻烦的其实是状态同步:编辑已有数据时,要预先勾选对应 checkbox,还要把原始值正确展示在标题栏。这部分逻辑一旦漏掉,用户就以为没加载成功。

















