layui 的 form.render("select") 是同步函数但不保证 dom 更新完成,需通过轮询检测 .layui-form-select 是否真实存在且可交互,表格场景应监听 table.on("rendered")。

form.render("select") 调用后并不等于渲染完成
layui 的 form.render("select") 是同步函数,但它只触发重绘逻辑,不保证 DOM 更新完毕。常见错误是调完就立刻操作 .layui-form-select 元素,结果查不到或宽高为 0——因为浏览器尚未完成样式计算和布局。
- 真正“渲染完成”的标志是
.layui-form-select容器已插入 DOM 且可见(offsetParent !== null) - 若在
layui.use(["form"], callback)内调用,确保 callback 已执行完毕;若在 AJAX success 中调用,需确认数据已写入<select></select>的innerHTML或appendChild - 动态插入
<option></option>后,必须等<select></select>自身存在、再调form.render("select"),顺序错一步就白干
如何可靠检测 select 渲染是否就绪
不能依赖定时器或固定延时,要查真实 DOM 状态。最稳的方式是轮询 + 条件退出:
- 检查
document.querySelector("select[lay-filter='xxx']")是否存在且非null - 再查其兄弟节点:
document.querySelector("select[lay-filter='xxx']").nextElementSibling?.classList.contains("layui-form-select"),有则说明 form.render 已生成包裹容器 - 进一步验证下拉面板是否可测:
document.querySelector(".layui-form-select dl")?.children.length > 0 - 封装成 Promise 更安全:
function waitForSelectRender(filter) {<br> return new Promise(resolve => {<br> const check = () => {<br> const sel = document.querySelector(`select[lay-filter="${filter}"]`);<br> const wrap = sel?.nextElementSibling;<br> if (wrap && wrap.classList.contains("layui-form-select") && wrap.querySelector("dl dd")) {<br> resolve();<br> } else {<br> requestAnimationFrame(check);<br> }<br> };<br> check();<br> });<br>}
表格行内 select 渲染完成的特殊判断点
在 table.render() 的 done 回调里调 form.render("select"),不代表每行的 select 都 ready——尤其是分页后新渲染的行,DOM 是异步挂载的。
- 别在
done里直接遍历所有select并查.layui-form-select,此时很多还没生成 - 正确做法:监听
table.on("rendered"),它在每次表格 DOM 完全更新后触发(包括翻页、排序、搜索) - 若某列用了
templet动态拼<select></select>,需在templet返回后加个标记,例如<select data-ready="false"></select>,再用 MutationObserver 监听该属性变true - 移动端要注意:
form.render()后首次点击可能仍无响应,需补一次select.focus()激活焦点管理
table.on("rendered") 是表格场景下唯一可信的全局就绪信号。











