我们工作、学习中,都会遇到联动需求,这里一套万能简易强大的代码送给大家
展示列表如图所示,这里以三级联动为例,多级联动以此类推...
修改数据查看效果:
先来看一下数据库——城市表,sql文件附在文末,有需要的可以自行下载:
这里的需求是公司新员工的数据(地址信息包含省、市、县),实体类如下所示:
前端(添加/修改)页面 select 下拉框 关键代码
<%-- ajax动态加载省市县下拉框--%>
<%-- onchange事件 函数中分别传入 下拉框选中的值 和对应需要 子下拉框(市)的字符串 --%>
省:
<select name="province.id" onchange="getCity(this.value,'city.id')">
<option value=''>===请选择===</option>
</select>
<%-- onchange事件 函数中分别传入 下拉框选中的值 和对应需要 子下拉框(县)的字符串 --%>
市:
<select name="city.id" onchange="getCity(this.value,'countyId')">
<option value=''>===请选择===</option>
</select>
<%-- 如有下一级,原理同上,这里以三级联动为例 --%>
县:
<select name="countyId">
<option value=''>===请选择===</option>
</select>
JavaScript关键代码,对应前端页面的onchange函数
<script>
/* 就绪函数 */
$(function () {
let pid = '${u.province.id}'; // 接收域对象省id的值
let sid = '${u.city.id}'; // 接收域对象市id的值
let xid = '${u.county.id}'; // 接收域对象县id的值
// 进入页面即加载省下拉框并赋值
// 第一个参数1即为数据库中所有省所对应的pid;第二个参数'province.id'为查出的结果要传的位置即(select下拉框name属性对应的值)
getCity(1, 'province.id', pid);
// 同理,参数一为对应市的pid(根据这个值可以查出一个市集合);参数二意义同上;
// 参数三即为回显要用的值;参数四为一个标记,判断是否是第一次进入该页面,下面在使用时会有解释
getCity(pid, 'city.id', sid, 1);
// 原理同上
getCity(sid, 'countyId', xid);
})
// 修改回显只需要在添加的联动代码基础上加入两个参数即可
// hxid为回显要用的值,也就是修改时根据对象id查询出来 该对象所在省市县的值;flag为旗帜,用于做标记
function getCity(pid, loc, hxid, flag) {
$.post(
"getCity", // 对应控制层的方法
{id: pid}, // 控制层需要接收的值
function (msg) { // msg为ajax请求成功后返回的值,这里是一个集合
let str = "<option value=''>==请选择==</option>"; // 初始化定义变量str
/* 这里flag判断存在目的主要是为了防止因为线程抢占资源而导致县下拉框被清空。
假设 没有flag,由于ajax是异步的,因此可能出现如下情况:
当加载市下拉框的时候县下拉框先加载完了,执行到这一步就又将县下拉框清空了,此时回显就会出现bug。
如果flag!=1 说明没有走就绪函数,也就意味着用户在修改联动数据,那么此时就将县区域清空。*/
if (loc == 'city.id' && flag != 1) {
$("[name='countyId']").html(str); // 此时str的值还是上面定义的
}
// 遍历集合并做字符串拼接
for (let i = 0; i < msg.length; i++) { // 以集合长度为循环条件
// msg[i].id为城市表的主键 作为option的value,msg[i].cityname为对应的城市名称供用户选择
str += "<option value='" + msg[i].id + "'>" + msg[i].cityname + "</option>";
}
// 将循环拼接后的字符串赋值到对应的loc(select下拉框)
$("[name='" + loc + "']").html(str);
// 回显代码:根据hxid的值回显,若没有传值,则为空字符串
$("[name='" + loc + "']").val(hxid);
}, "json" // json格式
)
}
</script>
flag判断存在的意义:为了防止因为线程抢占资源而导致县下拉框被清空。
假设 没有flag,由于ajax是异步的,因此可能出现如下情况:
当加载市下拉框的时候县下拉框先加载完了,执行到判断处时不加flag就又将县下拉框清空了,此时回显就会出现bug。
如果flag!=1 说明没有走就绪函数,也就意味着用户在修改联动数据,那么此时才将县区域清空。
最后附上后台三层框架代码,很简单
大功告成,以上以修改回显为例,经测试没有任何bug,添加的时候getCity函数可以不加hxid和flag参数,就绪函数也无需获取域对象。联动原理逻辑如上所示,灵活运用,更多需求以此类推即可。
最后附上添加页面的三级联动代码。(换汤不换药,结合修改更好理解)
/* 就绪函数 */
$(function () {
// 进入页面即加载省下拉框并赋值
getCity(1, 'province.id');
// 第一个参数1即为数据库中所有省所对应的pid;第二个参数'province.id'为查出的结果要传的位置即(select下拉框name属性对应的值)
})
function getCity(pid, loc) {
$.post(
"getCity", // 对应控制层的方法
{id: pid}, // 控制层需要接收的值
function (msg) { // msg为ajax请求成功后返回的值,这里是一个集合
let str = "<option value=''>==请选择==</option>"; // 初始化定义变量str
if (loc == 'city.id') {
$("[name='countyId']").html(str); // 此时str的值还是上面定义的
}
// 遍历集合并做字符串拼接
for (let i = 0; i < msg.length; i++) { // 以集合长度为循环条件
// msg[i].id为城市表的主键 作为option的value,msg[i].cityname为对应的城市名称供用户选择
str += "<option value='" + msg[i].id + "'>" + msg[i].cityname + "</option>";
}
// 将循环拼接后的字符串赋值到对应的loc(select下拉框)
$("[name='" + loc + "']").html(str);
}, "json" // json格式
)
}
如有错误,欢迎指出
Thanks