Layui实现省市区三级联动需动态加载、逐级控制:监听change事件,用axios或$.ajax按pid请求下级数据,清空下级select并重置value,追加option后必须调用form.render('select', 'filter')重绘UI,否则选项不可见或无法交互。

layui 的 select 怎么绑定省市区三级联动数据?
不能直接用 layui 自带的 select 标签写死三级选项,必须动态加载、逐级控制。核心是监听 change 事件,用 layui.form.render('select') 重绘新生成的下拉项。
常见错误是:第二级选完没清空第三级、异步请求返回后没调用 form.render()、或者把全部省市区数据一次性塞进页面导致首屏卡顿。
- 推荐把省市区 JSON 数据放在后端接口(如
/api/areas?level=1&pid=0),按需加载,减少初始体积 - 第一级(省)可预加载,但第二、三级务必延迟请求,避免无意义 IO
- 每次切换上级时,必须手动清空下级所有
option并重置value,否则用户可能提交脏数据
怎么用 axios 或 $.ajax 获取下级数据并填入 select?
layui 不内置 AJAX,得自己引入 axios 或用 jQuery 的 $.ajax。注意:请求成功后不能只改 innerHTML,必须用 layui.form.render('select') 激活新选项的样式和事件。
示例(第二级市的加载):
form.on('select(province)', function(data){
const pid = data.value;
$('#city').empty().append('<option value="">请选择市</option>');
$('#district').empty().append('<option value="">请选择区</option>');
axios.get('/api/areas?level=2&pid=' + pid).then(res => {
res.data.forEach(item => {
$('#city').append(`<option value="${item.id}">${item.name}</option>`);
});
form.render('select', 'city'); // 关键:指定 select 的 lay-filter 值或容器 ID
});
});
-
form.render('select', 'city')中第二个参数是容器的 lay-filter 属性值,不是 DOM ID;如果没设 lay-filter,就传 DOM ID(如'#city') - 不要在
success回调里再嵌套一次form.on,事件委托已由 layui 初始化完成 - 接口返回字段名要统一(如固定用
id和name),避免每层写不同 key
为什么选完省之后市下拉框没反应或显示空白?
大概率是 form.render() 没触发,或 DOM 节点被重复初始化。layui 对已渲染过的 select 再次调用 form.render() 会失效,除非先销毁再重建——但没必要,正确做法是只操作 option 内容并重新 render。
- 检查浏览器控制台是否报错
Cannot read property 'render' of undefined:说明form模块没加载,确认layui.use(['form'], callback)已执行 - 确认 HTML 中
select有lay-filter属性,且值与 JS 中form.on('select(xxx)')的 xxx 一致 - 避免在循环中多次调用
form.render(),应在所有option追加完毕后调用一次 - 移动端 Safari 下可能出现渲染延迟,可在
form.render()后加setTimeout(() => {}, 0)强制重排
有没有现成的省市区 JSON 或兼容 IE 的方案?
不建议前端硬编码完整省市区数据,尤其要兼容 IE 时,JSON 太大会触发 IE 的脚本超时。真要离线使用,至少按省拆分成对象字典,用 require 或模块方式按需引入。
更现实的做法是:用国家统计局最新代码(2023 版),后端吐出树形结构,前端只存一级缓存(省),二级(市)做内存缓存(const cityCache = {}),第三次请求直接读缓存。
- 免费 JSON 数据源可参考:
https://github.com/modood/Administrative-divisions-of-China(注意去重和更新时间) - IE11 下
axios需配合es6-promise和whatwg-fetchpolyfill - 如果项目已用
laytpl,可用模板预编译 option 字符串,比字符串拼接更安全
三级联动真正难的不是渲染,而是边界情况:比如某省直辖县没地级市、直辖市下直接是区、港澳台数据结构不一致。这些得在接口层归一化,别丢给前端 if-else。


















