JSP+Access手机销售系统:Java Web入门、避坑与二次开发实战拆解
2026/10/19 5:15:07
一句话总结:选择省 → 自动加载对应省下的市;选择市 → 自动加载对应市下的区,层层筛选,上一级改变,下一级选项自动更新。
两种实现方案: ①前端版三级联动:一次性把全部省市区 JSON 数据拿到前端,JS 筛选(作业最常用) ②后端接口版:选省份,请求接口拿该省的市;选市,请求拿区(真实项目)
<!-- 三个下拉框 select --> <select id="province"> <option value="">请选择省份</option> </select> <select id="city"> <option value="">请选择城市</option> </select> <select id="area"> <option value="">请选择区县</option> </select>// 模拟省市区数据源,真实项目会引入完整的省市区json文件 let areaData = [ { code: '410000', name: '河南省', children: [ { code: '410700', name: '新乡市', children: [ {code:'410702',name:'红旗区'}, {code:'410703',name:'卫滨区'}, {code:'410704',name:'凤泉区'} ] }, { code: '410100', name: '郑州市', children: [ {code:'410102',name:'中原区'}, {code:'410103',name:'二七区'} ] } ] }, { code: '110000', name: '北京市', children: [ { code: '110100', name: '北京市', children: [ {code:'110101',name:'东城区'}, {code:'110102',name:'西城区'} ] } ] } ] // 获取三个下拉框DOM let provinceSel = document.querySelector('#province'); let citySel = document.querySelector('#city'); let areaSel = document.querySelector('#area'); // 渲染省份下拉 let renderProvince = ()=>{ let html = '<option value="">请选择省份</option>'; areaData.forEach(item=>{ html += `<option value="${item.code}">${item.name}</option>` }) provinceSel.innerHTML = html; } // 根据省份code,渲染市 let renderCity = (provCode)=>{ // 清空市、区下拉 citySel.innerHTML = '<option value="">请选择城市</option>'; areaSel.innerHTML = '<option value="">请选择区县</option>'; // 找到选中的省份 let targetProvince = areaData.find(item=> item.code === provCode); if(!targetProvince) return; let html = ''; targetProvince.children.forEach(city=>{ html += `<option value="${city.code}">${city.name}</option>` }) citySel.innerHTML = html; } // 根据市code,渲染区 let renderArea = (cityCode)=>{ areaSel.innerHTML = '<option value="">请选择区县</option>'; // 遍历找城市 let targetCity = null; for(let p of areaData){ targetCity = p.children.find(c=> c.code === cityCode); if(targetCity) break; } if(!targetCity) return; let html = ''; targetCity.children.forEach(area=>{ html += `<option value="${area.code}">${area.name}</option>` }) areaSel.innerHTML = html; } // 省份切换事件 provinceSel.addEventListener('change', (e)=>{ let provCode = e.target.value; renderCity(provCode); }) // 城市切换事件 citySel.addEventListener('change',(e)=>{ let cityCode = e.target.value; renderArea(cityCode); }) // 页面加载初始化省份 renderProvince();逻辑:不一次性加载全部数据
优点:不用一次性加载巨大的省市区 JSON,节省带宽,适合线上项目 缺点:每次切换都要发请求
// 省份改变,请求城市 provinceSel.addEventListener('change', async (e)=>{ let provCode = e.target.value; // 请求接口获取城市列表 let res = await fetch(`/api/getCity?provCode=${provCode}`) let cityList = await res.json(); // 渲染城市下拉 })