三级联动效果,最终实现结果如下:
当点击河北切换省份,会产生联动,自动更新市级和县级, 当更新市级时,会自动更新县级
页面下拉菜单产生变化时,会触发事件,从而通过AJAX向服务器请求相关联的数据,获取到关联数据后,发送给前端,在不跳转页面的情况下,更新页面数据.
js中将每一块功能基本都提取了出来,放在不同的函数中分离调用执行. 每一块代码实现的功能都做了注释,函数式编程的好处大家都懂.
具体代码如下:
HTML代码
此处我直接将form,select写到了页面中, 并未更改至js文件中.
可以将该部分通过JS来生成,并放到一个容器,插入到页面中,实现零HTML代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form>
<select name="province" id="" class="province">
</select>
<select name="city" id="" class="city">
</select>
<select name="county" id="" class="county">
</select>
</form>
<script type="module">
import CREAT from "./js/CREAT.js";
var creat = new CREAT();
//creat.appendTo(插入的位置); JS中备注的地方是这里
</script>
</body>
</html>
node代码:
创建三个接口,来实现数据的交互,通过接收到不同接口,返回需要的数据,实现从服务端数据的获取.具体数据格式如下.
var http = require("http");
var querystring = require("querystring")
//省
var province=["海南","山东","河北"];
//市
var city=[
{
name:"海南",
has:["五指山","琼海"],
},
{
name:"河北",
has:["石家庄","保定","张家口"],
},
{
name:"山东",
has:["济南","烟台","威海"]
}
];
//县
var county=[
{
name:"五指山",
has:["通什镇", "南圣镇", "毛阳镇"],
},
{
name:"琼海",
has:["嘉积镇", "万泉镇", "石壁镇"],
},
{
name:"石家庄",
has:["长安区", "桥东区", "桥西区", "新华区", "井陉矿区"]
},
{
name:"保定",
has:["新市区", "北市区", "南市区", "满城县"]
},
{
name:"张家口",
has:["桥东区", "桥西区", "宣化区", "下花园区"]
},
{
name:"济南",
has:["历下区", "市中区", "槐荫区", "天桥区", "历城区"]
},
{
name:"烟台",
has:["芝罘区", "福山区", "牟平区", "莱山区", "长岛县"],
},
{
name:"威海",
has:["环翠区", "文登市", "荣成市", "乳山市"]
},
]
var server = http.createServer(function(req,res){
var data="";
res.writeHead(200,{
"content-type":"text/html;charset=utf-8",
"Access-Control-Allow-Origin":"*",
"Access-Control-Allow-Headers":"*",
})
req.on("data",function(_data){
data=_data;
})
req.on("end",function(){
var type=req.url.trim().split("?")[0].replace(/\//g,"");
if(req.method.toLowerCase()!=="get") return res.end("请求方式错误");
data=req.url.includes("?") ? req.url.trim().split("?")[1] : "";
//将请求数据转为数组
try{
data=JSON.parse(data);
}catch(e){
data=querystring.parse(data);
}
var o={};
//不同的请求类型,返回不同的数据
switch(type){
//传入的类型是省份,执行
case "province":
o.province=province;
o.city=city;
o.county=county;
break;
//传入的类型是市,执行
case "city":
o.city=city.reduce(function(value,item){
if(data["0"]===item.name)value=item.has;
return value;
},null)
break;
//传入的类型是县,执行
case "county":
o.county=county.reduce(function(value,item){
if(data["0"]===item.name)value=item.has;
return value;
},null)
break;
}
res.write(JSON.stringify(o));
res.end();
})
})
//开启服务提示
server.listen(4111,"172.20.61.59",function(){
console.log("服务开启成功");
})
JS代码:(ES6)
面向对象.
import QueryString from "./QueryString.js" //导入querystring方法,方便下面转换为querystring类型,此querystring方法代码不做黏贴,网上也有很多
export default class CREAT {
elem;
dataList;
type="province";
constructor(_type){
if(_type) this.type=_type;
this.elem=document.createElement("div");
this.ajax(this.type);
this.addEvent();
}
//将elem插入到dom中 . 这里我没有将select在js中创建,所以没用用elem,实现零html代码,需要将form和select创建后插入到elem中,然后在new 这个CREAT 类时,引用即可
appendTo(parent){
if(typeof parent==="string") parent=document.querySelector(parent);
parent.appendChild(this.elem);
}
//ajax,并带入两个参数,传输方式和数据
ajax(type,data){
data=[data];
if(data===undefined) data="";//如果没有带入数据,就设置为空字符串
data=QueryString.stringify(data);//将数据转为query形式,传入服务
var xhr = new XMLHttpRequest();
xhr.addEventListener("load",e=>this.loadHandler(e));
xhr.open("GET","http://172.20.61.59:4111/"+type+"/?"+data);
xhr.send();
}
loadHandler(e){
var xhr =e.currentTarget;
xhr.removeEventListener("load",e=>this.loadHandler(e));
var type=xhr.responseURL.trim().split("?")[0];//得到数据传输方式
if(type.slice(-1)==="/") type=type.slice(0,-1);
type=type.split("/").pop();
var o=JSON.parse(xhr.response);//将服务器返回的数据转换成JSON数组
this.dataList=o;//将返回的数据赋给datalist
switch(type){
case "province":
this.changeProvince(this.dataList,type);//如果类型是省,执行该方法
break;
case "city":
this.changeCity(this.dataList,type);//如果是市,执行该方法
break;
case "county":
this.changeCounty(this.dataList,type);//如果是县,执行该方法
break;
}
}
//获取,改变省份
changeProvince(data,type){
var parent = document.querySelector("."+type);
for(var i=0;i<data.province.length;i++){
var option=document.createElement("option");
option.innerHTML=data.province[i];
parent.appendChild(option);//最好用碎片容器
}
// parent.value=data;
this.ajax("city",parent.value)
}
//改变市
changeCity(data,type){
var parent = document.querySelector("."+type);
for(var i=0;i<data.city.length;i++){
var option=document.createElement("option");
option.innerHTML=data.city[i];
parent.appendChild(option);//此处最好用碎片容器
}
this.ajax("county",parent.value);
parent.value=data.city[0];
}
//改变县
changeCounty(data,type){
var parent = document.querySelector("."+type);
for(var i=0;i<data.county.length;i++){
var option=document.createElement("option");
option.innerHTML=data.county[i];
parent.appendChild(option);//此处最好用碎片容器
}
}
//给select下拉表单添加change事件,点击时放生改变
addEvent(){
var select1=document.querySelector(".province");
var select2=document.querySelector(".city");
select1.addEventListener("change",e=>this.changeHandler(e));
select2.addEventListener("change",e=>this.changeHandler(e));
}
//省 或 市 改变,触发事件,执行该函数
changeHandler(e){
var o =e.target.nextElementSibling;
//改变省份执行
if(e.target.className==="province"){
o.innerHTML="";//清空原来 市的select 中的内容
o.nextElementSibling.innerHTML="";
this.ajax(o.className,e.target.value);
}else{
//改变市, 执行
e.target.nextElementSibling.innerHTML="";清空原来 县的select 中的内容
this.ajax(o.className,e.target.value);
}
}
}