Demo来源:http://www.imuum.com/plugin-jquery-cityselect-js-provinces-linkage-effect.html

我把Demo改写成最多可以到5级联动,需要增加修改也很容易

数据来源,Java端通过Spring boot输出将实体类转成JSON对象,转换效率有点低

TreeItem.java

public class TreeItem {
    private String id;
    private String pId;
    private String name;
    private String extra;
    public TreeItem(String id,String pId,String name) {
        this.id = id;
        this.pId = pId;
        this.name = name;

    }
    public TreeItem(String id,String pId, String name, String extra) {
        this.id = id;
        this.pId = pId;
        this.name = name;
        this.extra = extra;
    }
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getpId() {
        return pId;
    }

    public void setpId(String pId) {
        this.pId = pId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Tree.java

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Tree {
    private List<TreeItem> nodes;

    public Tree(List<TreeItem> nodes){
        this.nodes = nodes;
    }

    public Map buildTree(){
        List<Map<String,Object>> list=new ArrayList<>();
        for (TreeItem node : nodes) {
            String id = node.getId();
            if (node.getpId() == null) {
               list.add(build(node));
            }
        }
        Map treeMap=new HashMap<>();
        treeMap.put("citylist",list);
       return treeMap;
    }

    private Map build(TreeItem node){
        List<TreeItem> children = getChildren(node);
        List<Map<String,Object>> list=new ArrayList<>();
        Map<String,Object> map=new HashMap<>();
        map.put("node",node);
        if (children.isEmpty()) {
            return map;
        }
        for (TreeItem child : children) {
            list.add(build(child));
        }
        map.put("children",list);
        return map;
    }

    private List<TreeItem> getChildren(TreeItem node){
        List<TreeItem> children = new ArrayList<TreeItem>();
        String id = node.getId();
        for (TreeItem child : nodes) {
            if (id.equals(child.getpId())) {
                children.add(child);
            }
        }
        return children;
    }
}

通过调用Tree.buildTree函数就可以生成我们需要的json数据

然后就是前端页面了,预设值部分还没有做

index.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>基于jQuery+JSON的省市联动效果</title>
<script type="text/javascript" src="js/jquery.2.1.1.min.js"></script>
<script type="text/javascript" src="js/jquery.cityselect2.js"></script>
<script type="text/javascript">
$(function(){
	$("#city").citySelect({
		nodata:null,
		required:false
	}); 
});
</script>
</head>

<body>
<div id="main">  
  <div class="demo">
  	<h3>设置省份、城市、地区(县)的默认值</h3>
    <p>三级联动</p>
    <div id="city">
  		<select class="s0"></select> 
    	<select class="s1" disabled="disabled"></select>
      <select class="s2" disabled="disabled"></select>
      <select class="s3" disabled="disabled"></select>
      <select class="s4" disabled="disabled"></select>
    </div>
  </div>
  </div>
  <br />
<br />
</div>
</body>
</html>



cityselect2.js

/*
Ajax 多级联动
http://code.ciaoca.cn/
日期:2012-7-18

settings 参数说明
-----
url:省市数据josn文件路径
prov:默认省份
city:默认城市
dist:默认地区(县)
nodata:无数据状态
required:必选项
------------------------------ */
(function($){
	$.fn.citySelect=function(settings){
		if(this.length<1){return;};

		// 默认值
		settings=$.extend({
			url:"js/city.js",
			prov:null,
			city:null,
			dist:null,
			nodata:null,
			required:true
		},settings);

		var box_obj=this;
		var s0_obj=box_obj.find(".s0");
		var s1_obj=box_obj.find(".s1");
		var s2_obj=box_obj.find(".s2");
		var s3_obj=box_obj.find(".s3");
		var s4_obj=box_obj.find(".s4");
	
		var prov_val=settings.prov;
		
		var select_prehtml=(settings.required) ? "" : "<option value=''>请选择</option>";
		var city_json;

		//获取当前选择框前面的选择框
		var getPreS=function(s){
			if(s==s1_obj) return s0_obj;
			if(s==s2_obj) return s1_obj;
			if(s==s3_obj) return s2_obj;
			if(s==s4_obj) return s3_obj;
			return null;
		}
		//获取当前选择框的下一个选择框
		var getNextS=function(s){
			if(s==s0_obj) return s1_obj;
			if(s==s1_obj) return s2_obj;
			if(s==s2_obj) return s3_obj;
			if(s==s3_obj) return s4_obj;
			return null;
		}
		//获取当前选择框的序号
		var getSelectN=function(s){
			if(s==s0_obj) return 0;
			if(s==s1_obj) return 1;
			if(s==s2_obj) return 2;
			if(s==s3_obj) return 3;
			return 4;
		}
		//根据当前选择框的值获取json数据的children
		var getCityChildren=function(s){
			var s0_id=s0_obj.get(0).selectedIndex;
			var s1_id=s1_obj.get(0).selectedIndex;
			var s2_id=s2_obj.get(0).selectedIndex;
			var s3_id=s3_obj.get(0).selectedIndex;
			var s4_id=s4_obj.get(0).selectedIndex;
			if(!settings.required){
				s0_id--;
				s1_id--;
				s2_id--;
				s3_id--;
				s4_id--;
			};
			if(s==s0_obj) return city_json.citylist[s0_id].children;
			if(s==s1_obj) return city_json.citylist[s0_id].children[s1_id].children;
			if(s==s2_obj) return city_json.citylist[s0_id].children[s1_id].children[s2_id].children;
			if(s==s3_obj) return city_json.citylist[s0_id].children[s1_id].children[s2_id].children[s3_id].children;
			return null;
		}
		//根据序号隐藏选择框
		var hidSubSelect=function(n){
			if(n<1){
				s1_obj.empty().attr("disabled",false);
				if(settings.nodata=="none"){
					s1_obj.css("display","none");
				}else if(settings.nodata=="hidden"){
					s1_obj.css("visibility","hidden");
				};
			}
			if(n<2){
				s2_obj.empty().attr("disabled",false);
				if(settings.nodata=="none"){
					s2_obj.css("display","none");
				}else if(settings.nodata=="hidden"){
					s2_obj.css("visibility","hidden");
				};
			}
			if(n<3){
				s3_obj.empty().attr("disabled",false);
				if(settings.nodata=="none"){
					s3_obj.css("display","none");
				}else if(settings.nodata=="hidden"){
					s3_obj.css("visibility","hidden");
				};
			}
			if(n<4){
				s4_obj.empty().attr("disabled",false);
				if(settings.nodata=="none"){
					s4_obj.css("display","none");
				}else if(settings.nodata=="hidden"){
					s4_obj.css("visibility","hidden");
				};
			}
		}

		// 赋值地区(县)函数
		var distStart=function(s){
			
			var current_id=s.selectedIndex;
			if(!settings.required){
				current_id--;
			};
			hidSubSelect(getSelectN(s));
			if(current_id<0||typeof(getCityChildren(s))=="undefined"||getCityChildren(s)==null){
				if(settings.nodata=="none"){
					getNextS(s).css("display","none");
				}else if(settings.nodata=="hidden"){
					getNextS(s).css("visibility","hidden");
				};
				return;
			};
			
			// 遍历
			temp_html=select_prehtml;
			$.each(getCityChildren(s),function(i,dist){
				temp_html+="<option value='"+dist.node.id+"'>"+dist.node.name+"</option>";
			});
			getNextS(s).html(temp_html).attr("disabled",false).css({"display":"","visibility":""});
		};

		var init=function(){
			// 遍历赋值省份下拉列表
			temp_html=select_prehtml;
			$.each(city_json.citylist,function(i,prov){
				temp_html+="<option value='"+prov.node.id+"'>"+prov.node.name+"</option>";
			});
			s0_obj.html(temp_html);

			// 若有传入省份与市级的值,则选中。(setTimeout为兼容IE6而设置)
			setTimeout(function(){
				if(settings.prov!=null){
					prov_obj.val(settings.prov);
					cityStart();
					setTimeout(function(){
						if(settings.city!=null){
							city_obj.val(settings.city);
							distStart();
							setTimeout(function(){
								if(settings.dist!=null){
									dist_obj.val(settings.dist);
								};
							},1);
						};
					},1);
				};
			},1);

			// 选择省份时发生事件
			s0_obj.bind("change",function(){
				distStart(s0_obj);
			});
			s1_obj.bind("change",function(){
				distStart(s1_obj);
			});
			s2_obj.bind("change",function(){
				distStart(s2_obj);
			});
			s3_obj.bind("change",function(){
				distStart(s3_obj);
			});
			s4_obj.bind("change",function(){
				distStart(s4_obj);
			});
		};

		// 设置省市json数据
		if(typeof(settings.url)=="string"){
			$.getJSON(settings.url,function(json){
				city_json=json;
				init();
			});
		}else{
			city_json=settings.url;
			init();
		};
	};
})(jQuery);


把树的建立放到了前端js来建立

后端直接输出List<TreeItem>对象,框架自动输出JSON数组,前端js递归建树的代码如下

var districts;
        var arrayToTree=function(parentId) {
            var temp = [];
            for (var index in districts) {
                if (districts[index].pId == parentId) {
                    var children=arrayToTree(districts[index].id);
                    temp.push({
                        node: districts[index],
                        children: children
                    });
                }
            }
           return temp;
        };
        var buildTree= function (parentId) {
            var temp = {citylist:[]};
            for (var index in districts) {
                if (districts[index].id == parentId) {
                    temp.citylist.push({
                        node: districts[index],
                        children: arrayToTree(districts[index].id)
                    });
                }
            }
            return temp;
        };

在得到数据的时候修改一下

$.getJSON(settings.url, function (json) {
                    districts=json;
					city_json = buildTree('000');//000是根节点的ID
init();
}



jquery.cityselect.js最后的Javascript代码如下

/*
多级联动 刘放
日期:2016-8-22

settings 参数说明
-----
url:省市数据josn文件路径
s0:默认省份
s1:默认市
s2:默认县
s3:默认乡镇
s4:默认村
nodata:无数据状态  如果需要隐藏则填写none或者hidden
required:必选项

依赖于web-storage-cache.min.js
------------------------------ */
(function($){
	$.fn.citySelect=function(settings){
		if(this.length<1){return;};
		var wsCache = new WebStorageCache();
		// 默认值
		settings=$.extend({
			url:null,
			s1:null,
			s2:null,
			s3:null,
			s4:null,
			s0:null,
			nodata:null,
			required:true
		},settings);

		var box_obj=this;
		var s0_obj=box_obj.find(".s0");
		var s1_obj=box_obj.find(".s1");
		var s2_obj=box_obj.find(".s2");
		var s3_obj=box_obj.find(".s3");
		var s4_obj=box_obj.find(".s4");
        var text_obj=box_obj.find("input[type=hidden]");

        var setTextObj=function(){
            if(text_obj.length>0) {
                if(s4_obj.val()!=="") {
                    text_obj.val(
                    s0_obj.find("option:selected").text()+
                    s1_obj.find("option:selected").text()+
                    s2_obj.find("option:selected").text()+
                    s3_obj.find("option:selected").text()+
                    s4_obj.find("option:selected").text());
                }else{
                    text_obj.val("");
                }
            }
        };

        var prov_val=settings.prov;
		
		var select_prehtml=(settings.required) ? "" : "<option value=''>请选择</option>";
		var city_json;

		//获取当前选择框前面的选择框
		var getPreS=function(s){
			if(s==s1_obj) return s0_obj;
			if(s==s2_obj) return s1_obj;
			if(s==s3_obj) return s2_obj;
			if(s==s4_obj) return s3_obj;
			return null;
		}
		//获取当前选择框的下一个选择框
		var getNextS=function(s){
			if(s==s0_obj) return s1_obj;
			if(s==s1_obj) return s2_obj;
			if(s==s2_obj) return s3_obj;
			if(s==s3_obj) return s4_obj;
			return null;
		}
		//获取当前选择框的序号
		var getSelectN=function(s){
			if(s==s0_obj) return 0;
			if(s==s1_obj) return 1;
			if(s==s2_obj) return 2;
			if(s==s3_obj) return 3;
			return 4;
		}
		//根据当前选择框的值获取json数据的children
		var getCityChildren=function(s){
			var s0_id=s0_obj.get(0).selectedIndex;
			var s1_id=s1_obj.get(0).selectedIndex;
			var s2_id=s2_obj.get(0).selectedIndex;
			var s3_id=s3_obj.get(0).selectedIndex;
			var s4_id=s4_obj.get(0).selectedIndex;
			if(!settings.required){
				s0_id--;
				s1_id--;
				s2_id--;
				s3_id--;
				s4_id--;
			};
			if(s===s0_obj) return city_json.list[s0_id].children;
			if(s===s1_obj) return city_json.list[s0_id].children[s1_id].children;
			if(s===s2_obj) return city_json.list[s0_id].children[s1_id].children[s2_id].children;
			if(s===s3_obj) return city_json.list[s0_id].children[s1_id].children[s2_id].children[s3_id].children;
			return null;
		}
		//根据序号隐藏选择框
		var hidSubSelect=function(n){
			if(n<1){
				s1_obj.empty().attr("disabled",false);
				if(settings.nodata=="none"){
					s1_obj.css("display","none");
				}else if(settings.nodata=="hidden"){
					s1_obj.css("visibility","hidden");
				};
			}
			if(n<2){
				s2_obj.empty().attr("disabled",false);
				if(settings.nodata=="none"){
					s2_obj.css("display","none");
				}else if(settings.nodata=="hidden"){
					s2_obj.css("visibility","hidden");
				};
			}
			if(n<3){
				s3_obj.empty().attr("disabled",false);
				if(settings.nodata=="none"){
					s3_obj.css("display","none");
				}else if(settings.nodata=="hidden"){
					s3_obj.css("visibility","hidden");
				};
			}
			if(n<4){
				s4_obj.empty().attr("disabled",false);
				if(settings.nodata=="none"){
					s4_obj.css("display","none");
				}else if(settings.nodata=="hidden"){
					s4_obj.css("visibility","hidden");
				};
			}
		}

		// 赋值地区(县)函数
		var distStart=function(s){
			if($(s).val()==="") return;
			var current_id=s.selectedIndex;
			if(!settings.required){
				current_id--;
			};
			hidSubSelect(getSelectN(s));
			if(current_id<0||typeof(getCityChildren(s))=="undefined"||getCityChildren(s)==null){
				if(settings.nodata=="none"){
					getNextS(s).css("display","none");
				}else if(settings.nodata=="hidden"){
					getNextS(s).css("visibility","hidden");
				};
				return;
			};

            var next_obj=getNextS(s);//获取到下一个组件
            if(next_obj==null) return;
			// 遍历
			temp_html=select_prehtml;
			$.each(getCityChildren(s),function(i,dist){
				temp_html+="<option value='"+dist.node.id+"'>"+dist.node.name+"</option>";
			});
            next_obj.html(temp_html).attr("disabled",false).css({"display":"","visibility":""});
            if($(s).val()!==""){
                distStart(next_obj);
            }
		};

		var initCity=function(){
			// 遍历赋值省份下拉列表
			temp_html=select_prehtml;
			$.each(city_json.list,function(i,prov){
				temp_html+="<option value='"+prov.node.id+"'>"+prov.node.name+"</option>";
			});
			s0_obj.html(temp_html);
			distStart(s0_obj);
			// 若有传入省份与市级的值,则选中。(setTimeout为兼容IE6而设置)
			setTimeout(function(){
				if(settings.s0!==null&&settings.s0!==""){
					s0_obj.val(settings.s0);
					distStart(s0_obj);
					setTimeout(function(){
						if(settings.s1!=null){
							if(s1_obj==null) return;
							s1_obj.val(settings.s1);
							distStart(s1_obj);
							setTimeout(function(){
								if(s2_obj==null) return;
								if(settings.s2!=null){
									s2_obj.val(settings.s2);
									distStart(s2_obj);
									setTimeout(function(){
										if(s3_obj==null) return;
										if(settings.s3!=null){
											s3_obj.val(settings.s3);
											distStart(s3_obj);
											setTimeout(function(){
												if(s4_obj==null) return;
												if(settings.s4!=null){
													s4_obj.val(settings.s4);
												};
											},1);
										};
									},1);
								};
							},1);
						};
					},1);
				};
			},1);
            setTimeout(function(){
                // 选择省份时发生事件
                s0_obj.bind("change",function(){
                    distStart(s0_obj);
                });
                s1_obj.bind("change",function(){
                    distStart(s1_obj);
                });
                s2_obj.bind("change",function(){
                    distStart(s2_obj);
                });
                s3_obj.bind("change",function(){
                    distStart(s3_obj);
                });
                s4_obj.bind("change",function(){
                    distStart(s4_obj);
                    setTextObj();
                });
            },50);
		};

        var districts;
        var arrayToTree=function(parentId) {
            var temp = [];
            for (var index in districts) {
                if (districts[index].pId == parentId) {
                    var children=arrayToTree(districts[index].id);
                    temp.push({
                        node: districts[index],
                        children: children
                    });
                }
            }
           return temp;
        };
        var buildTree= function (parentId) {
            var temp = {list:[]};
            for (var index in districts) {
                if (districts[index].id == parentId) {
                    temp.list.push({
                        node: districts[index],
                        children: arrayToTree(districts[index].id)
                    });
                }
            }
            return temp;
        };
		// 设置省市json数据
		if(typeof(settings.url)=="string"){
			city_json=wsCache.get("allCity");
			if(city_json!==undefined&&city_json!==null){
				initCity();
			}
			else {
				$.getJSON(settings.url, function (json) {
                    districts=json;
					city_json = buildTree('320000000000');//前端建好树
					wsCache.set('allCity', city_json, {exp : 60*12});//缓存12*60s
					initCity();
				});
			}
		}else{
			city_json=settings.url;
			initCity();
		};
	};
})(jQuery);