layui 2.x 的 select 组件不支持 optgroup,需用 lay-select 自定义模板手动构建分组结构,并通过隐藏域同步值;layUI 3.0+ 已支持 optgroup,或可选用 tom-select 等第三方组件。

layui 的 select 组件原生不支持 optgroup
layui 2.x 的 form.render('select') 渲染逻辑会忽略 HTML 原生的 <optgroup> 标签,直接把所有 <option> 扁平化渲染成下拉项,分组标题不会显示,也无法折叠展开。
这不是你写错了标签,而是 layui 的 select 模块压根没解析 optgroup 的 DOM 结构 —— 它只认 option[value] 和文本内容。
用 lay-select 自定义模板 + 手动构造分组结构
必须绕过默认渲染,改用「自定义模板」方式,用 lay-select 属性配合 JS 动态生成带分组的下拉菜单。核心是:不依赖 form.render(),自己控制 DOM 结构和事件。
- HTML 中写一个空的
<div class="layui-input-inline"><div lay-select=""></div></div>,不要放select标签 - JS 初始化时传入带
group字段的数据结构,例如:[{ group: '前端框架', options: [{value: 'vue', title: 'Vue.js'}, {value: 'react', title: 'React'}] }, { group: '后端语言', options: [{value: 'node', title: 'Node.js'}, {value: 'python', title: 'Python'}] }] - 在
success回调或初始化后,用lay.select.render()(注意不是form.render)并指定item模板,手动拼出<dl class="layui-anim"><dt>前端框架</dt><dd lay-value="vue">Vue.js</dd></dl>这类结构
注意 lay-select 的事件绑定和值同步问题
手动构造后,change 事件不会自动触发,且表单提交时该下拉框的值不会被 form.val() 采集到 —— 因为它根本不是 select 元素。
- 必须显式监听
click或lay-select的change事件(如果用了lay.select.render),然后手动更新隐藏域:<input type="hidden" name="framework" id="framework-val">
- 每次选中后要执行
$('#framework-val').val(selectedValue),否则form.on('submit')拿不到值 - 若需初始值回填,不能靠
value属性,得 JS 主动调用lay.select.val('framework-val', 'vue')(需自行封装或查 DOM 更新文本) - 禁用状态、搜索过滤、多选等高级功能需全部手写,layui 原生 select 插件不接管
更稳妥的替代方案:换用 layUI 3.0+ 的 <code>select(beta 版)或第三方组件
layui 官方在 3.0 beta 中已重写 select,开始支持 optgroup,但目前未正式发布,文档缺失,API 不稳定;生产环境建议评估迁移成本。
如果项目允许引入轻量依赖,tom-select 或 choices.js 都能原生支持 optgroup,且与 layui 布局兼容性好(只替换下拉部分 DOM,不影响其他 form 元素)。
真正卡住的往往不是怎么画出分组样式,而是表单数据联动、校验、重置这些细节 —— 手动实现一遍就会发现,optgroup 只是表象,背后是整套选择器生命周期的接管。


















