原生 select + ajax 更可控,formSelects 非官方维护、兼容性差、级联逻辑难调试;省市区数据量小,用 Layui 自带 $.ajax 和 form.render() 即可干净实现。
layui 用 formSelects 还是原生 select + ajax?
直接说结论:原生 select + ajax 更可控,formselects 是第三方扩展,layui 官方不维护,新版兼容性差、级联逻辑黑盒难调试。
真实项目里,省市区数据量不大(全国约 4000+ 条),没必要引入额外依赖。用 Layui 自带的 $.ajax 和 form.render() 就能干净实现。
- 省下
formSelects-v4.js加载和初始化开销 - 避免
formSelects在laydate或layer同页时的 z-index 冲突 - 后端返回结构稍有变化(比如字段名是
code/name而非value/title),自己写 JS 更容易适配
三级联动中「市」和「区」下拉为何始终空着?
大概率是没清空下级选项,或没触发 form.render('select')。
Layui 的 select 不会自动响应 DOM 变更,手动拼 option 后必须显式重渲染:
- 选省后,先清空市、区的
select内容:$('#city').empty().append('<option value='\"\"'>请选择城市</option>') - 再填入新
option,最后调用form.render('select') - 漏掉
form.render(),UI 上就永远看不到新选项 - 如果用了
disabled属性控制可选状态,记得同步移除,否则即使有选项也无法点击
接口返回的省市区数据格式怎么对接最省事?
别硬套官方示例的嵌套 JSON,平铺数组 + pid 字段最稳妥。
后端返回类似:
[{"id":"110000","name":"北京市","pid":"0"},{"id":"110100","name":"市辖区","pid":"110000"},{"id":"110101","name":"东城区","pid":"110100"}]
前端按 pid 过滤即可,比递归解析树结构简单得多:
- 省:
list.filter(item => item.pid === '0') - 市:选中省
id后,list.filter(item => item.pid === selectedProvinceId) - 区:同理,用上一级
id当pid过滤 - 注意字符串比较:后端给的
id是字符串,别用===比数字
用户切换省之后,之前选的市/区值还在表单里怎么办?
这是典型脏数据问题 —— UI 清了,但 select 的 value 没重置,提交时仍会带上旧值。
- 每次清空下拉时,顺手设值:
$('#city').val('').trigger('change') -
trigger('change')是为了通知 Layui 表单验证模块该字段已变更 - 如果用了
lay-verify="required",不重置value可能导致校验失败或提示残留 - 更彻底的做法:在
change回调里统一做「上级变动 → 下级清空 + 值重置 + 校验清除」










