Layui原生select分组必须手写HTML的<optgroup>结构,不解析JS数据,需提前在HTML中写好完整嵌套结构并调用form.render('select','filter');动态更新时须拼接完整HTML字符串替换innerHTML,再重新render;复杂场景建议改用formSelects插件。

layui原生select怎么写
必须手写 HTML 的 <optgroup> 结构,Layui 不解析 JS 数据、不自动拼分组标签。你给它什么 DOM,它就渲染什么 DOM。
常见错误是写个空 <select>,再用 form.render('select') 想让它“读懂”你传的数组对象——它读不懂。
- HTML 里得提前写好完整的嵌套结构:
<optgroup label="华北"><option value="bj">北京</option></optgroup> -
label值原样显示,不支持变量或模板语法 - 每个
<optgroup>下至少有一个<option>,否则可能被浏览器忽略或渲染异常 - 写完 HTML 后,必须调用
form.render('select', 'filter')(filter 是你的lay-filter值)才能启用 Layui 样式
动态加载分组数据时怎么更新 select
没有“自动刷新分组”的 API,只能手动拼 HTML 字符串,再用 innerHTML 替换整个 <select> 内容,最后重新 form.render()。
如果你用 $('#xxx').empty().append(...) 只加 <option>,<optgroup> 就丢了——分组直接消失。
- 后端返回的数据格式建议是类似:
[{group: "华东", options: [{value:"sh", title:"上海"}]}] - 前端遍历拼字符串:
html += '<optgroup label="' + g.group + '">'; g.options.forEach(o => html += '<option value="' + o.value + '">' + o.title + '</option>'); html += '</optgroup>' - 替换时用
dom.innerHTML = html,别用append或appendChild单个节点 - 确保
form.render('select', 'your-filter')在 DOM 更新完成之后调用,比如放在$.ajax的success回调末尾
为什么用了
大概率是 form.render('select') 调用时机不对,或者 DOM 被破坏了层级结构。
典型现象:下拉框展开后只有空白项、分组标题看不见、选项挤在顶部——说明 <optgroup> 标签没被正确保留在最终渲染的 DOM 中。
- 检查是否用了
element.innerHTML = ''清空后再填内容,却忘了把<optgroup>一起拼进去 - 确认浏览器开发者工具 Elements 面板里,
<select>内部是否真实存在<optgroup>元素(不是被转成普通<div>) - Layui 渲染依赖原始语义化结构,一旦你用 JS 把
<optgroup>层级打平或删掉,它就再也识别不了分组逻辑 - 如果用了 jQuery,避免
.children().remove()这类粗暴清空方式;改用.html(htmlString)一次性替换全部内容
复杂场景别硬扛:该换 formSelects 就换
需要搜索、多选、无限层级分组、远程加载、拼音检索——这些都不是原生 select + <optgroup> 能解决的。
这时候直接上 formSelects 插件更省事,它把分组逻辑封装好了,支持按 group 字段自动渲染,还带缓存、防抖、皮肤定制。
- 引入
formSelects-v4.js和对应 CSS - HTML 写
<select id="xxx" multiple></select>,不用写任何<optgroup> - 配置里传
data数组,每项带group字段:{name: "北京", value: "bj", group: "华北"} - 初始化时开
search: true和groups: true,分组+搜索就都有了
原生方案只适合静态、简单、分组层级固定的下拉;只要业务稍一复杂,手拼 HTML 的维护成本就远高于引入一个轻量插件。


















