ES6面向对象三级级联省、市、区菜单
实现目标:
nodejs加ES6面向对象实现省市县的三级级联菜单
接口文档
项目列表接口
index.html:http://10.9.72.220:4001
URL :http://10.9.72.220:4001
Method :GET
DataType :
请求消息: QueryString
响应消息: JSON
接口名称
1、?type=province
?type=city
?type=district
2、http://10.9.72.220:4001/province/
http://10.9.72.220:4001/city/
http://10.9.72.220:4001/district/
获取省
接口名 province
请求 :province
响应 :
{province:[“北京”,“天津”,“河北”,“山西”,“内蒙古”…]}
获取市
接口名 city
请求 :province
响应 :
{city:[“石家庄”,“唐山”,“秦皇岛”,“邯郸”,“邢台”…]}
获取区县
接口名 district
请求 :city
响应 :
{city:[“长安区”,“桥东区”,“桥西区”,“新华区”,“井陉矿区”…]}
代码如下
index.js ES6面向对象
import Component from "./Component.js";
export default class Sanji extends Component {
selector;
constructor() {
super();
//获取省,返回数据data={北京: "北京", 天津: "天津", 河北: "河北", 山西: "山西", 内蒙古: "内蒙古", …}
this.ajax("GET", "province").then((res) => {
var data = JSON.parse(res);
// 执行创建渲染省createProvince
this.createProvince(data, "province");
});
}
//初始化创建
createProvince(_data, _province) {
var data = _data;
var province = _province;
// 创建省的select
var select = document.createElement("select");
var str;
// 遍历data创建option标签并放入省的select菜单中
for (let prop in data) {
str += `<option value=${prop}>${prop}</option>`;
}
select.innerHTML = str;
// 将当前select列表classname命名为province
select.setAttribute("class", province);
//将创建好的省放入div中
this.elem.appendChild(select);
this.createSelect();
}
createSelect() {
// 获取创建好的省列表
this.selector = document.querySelector("select");
// 获取当前这个省
var value = this.selector.value;
// 以province为key,城市名为value创建对象并带入初始化处理城市数据的函数getCity
var keys = {};
keys[this.selector.className] = value;
this.getCity(keys);
}
getCity(_keys) {
var keys = _keys;
//将初始化情况下的省发到服务器获取该省下的市的数据
this.ajax("GET", "city", keys).then((res) => {
var data = JSON.parse(res);
// 根据市的数据执行初始化创建城市select列表
this.createCity(data, "city");
// 对省的改变进行事件侦听,当省改变时,对应城市和区也要改变
this.selector.addEventListener("change", (e) => {
this.changeHandler(e);
});
});
}
createCity(_data, _city) {
var data = _data;
var city = _city;
var keys = {};
// 创建select列表
var select = document.createElement("select");
var str;
// 遍历data创建option标签并放入初始化市的select菜单中
for (let prop in data) {
str += `<option value="${prop}">${prop}</option>`;
}
select.innerHTML = str;
// 将当前select列表classname命名为市
select.setAttribute("class", city);
this.elem.appendChild(select);
// 更新keys,使keys指向初始化城市名
for (var prop in data) {
keys[city] = prop;
}
// 将data和城市名带入获取初始化地区名中
this.getDistrict(data, "district", keys);
// 将创建的市列表放入div
}
getDistrict(_data, _district, _keys = "") {
var keys = _keys;
var data = _data;
var district = _district;
// 创建初始化区,使用的数据是请求市时服务端发来的数据
var select = document.createElement("select");
var str;
// 遍历创建初始化区的option
for (var i = 0; i < data[keys.city].length; i++) {
str += `<option value="${data[keys.city][i]}">${
data[keys.city][i]
}</option>`;
}
select.innerHTML = str;
// 将当前select列表classname命名为区
select.setAttribute("class", district);
this.elem.appendChild(select);
}
//______________________________________________
//到此为止,一打开网页的初始化效果创建完毕,下面进行更改省,市,区时对应列表的改变
changeHandler(e) {
var value = this.selector.value;
// value为当前改变的省份
var keys = {};
keys[e.target.className] = value;
// 设置当前keys.province为当前省,并获取列表为城市的那个列表
var select = document.querySelector(".city");
// 向服务器发送请求获取当前更改省的数据
this.ajax("GET", "province", keys).then((res) => {
var data = JSON.parse(res);
var str;
// 遍历循环得到的省的数据将该省的城市更新到城市列表中
for (let prop in data[this.selector.value]) {
str += `<option value="${prop}">${prop}</option>`;
}
select.innerHTML = str;
this.elem.appendChild(select);
var value = select.value;
// 重新设置keys.city的值为当前城市,并执行更新该城市下的区
var keys = {};
keys[select.className] = value;
this.changeDistrict(keys);
});
}
changeDistrict(_keys) {
//改变省的时候,市和区跟着改变
var keys = _keys;
// 获取当前城市向服务器请求该城市下区的信息数据
var select = document.querySelector(".city");
this.ajax("GET", "district", keys).then((res) => {
var data = JSON.parse(res);
// 将当前获取的该城市下区的数据带入并更新区的列表
this.upDateDistrict(data, "district");
});
// 只改变当前省的城市,区重新改变
// 侦听事件,当改变当前城市时,改变对应区的名称
select.addEventListener("change", (e) => {
var key = {};
key["city"] = select.value;
// 向数据库请求当前改变城市的区的数据
this.ajax("GET", "district", key).then((res) => {
var selectDistrict = document.querySelector(".district");
var data = JSON.parse(res);
var str;
// 遍历获取的数据将当前新改变城市下的区重新列举
for (var i = 0; i < data.length; i++) {
str += `<option value="${data[i]}">${data[i]}</option>`;
}
selectDistrict.innerHTML = str;
});
});
}
// 改变省的时候,市下的区跟着改变
upDateDistrict(_data, _district) {
var data = _data;
var district = _district;
// 获取区的列表,循环遍历新数据将区的数据重新写入区
var select = document.querySelector(".district");
var str;
for (var i = 0; i < data.length; i++) {
str += `<option value="${data[i]}">${data[i]}</option>`;
}
select.innerHTML = str;
this.elem.appendChild(select);
}
appendTo(parent) {
super.appendTo(parent);
}
// ajax请求
ajax(method = "GET", type, data) {
var url = "http://10.9.72.220:4001/" + type;
var str = "";
if (data) {
for (var prop in data) {
str += prop + "=" + data[prop] + "&";
}
} else {
data = null;
}
str = str.slice(0, -1);
return new Promise(function (resolve, reject) {
if (method.toLowerCase() === "get") {
url += "?" + str;
}
var xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.send(method.toLowerCase() === "get" ? null : str);
xhr.onload = function () {
resolve(xhr.response);
};
xhr.onerror = function () {
reject();
};
});
}
}
index.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>
<style>
.warp{
margin: 0 auto;
height: 200px;
width: 400px;
}
</style>
</head>
<body>
<div class="warp"></div>
<script type="module">
import Sanji from "./js/index.js"
let sanji=new Sanji()
sanji.appendTo(".warp")
</script>
</body>
</html>
server.js前端与服务器通信
const { create } = require("domain");
var http = require("http");
var querystring = require("querystring");
var data = require("../data/data.js");
var server = http.createServer(createChannel);
var req, res;
function createChannel(_req, _res) {
req = _req;
res = _res;
var datas = "";
res.writeHead(200, {
"content-type": "text/html;charset=utf-8",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Headers": "*",
});
req.on("data", function (_data) {
datas += _data;
console.log(datas)
});
req.on("end", function () {
var type = req.url.trim().split("?")[0].replace(/\//g, "");
if (req.method.toLowerCase() === "get") {
if (req.url.includes("favicon.ico")) return res.end();
datas = req.url.includes("?") ? req.url.split("?")[1] : "";
}
try {
datas = JSON.parse(data);
} catch(e) {
datas = data ? querystring.parse(datas) : {};
}
var o = {};
switch (type) {
case "province":
if (JSON.stringify(datas) === "{}") {
for (var prop in data) {
o[prop] = prop;
}
} else {
o[datas.province] = data[datas.province];
}
break;
case "city":
for (var prop in data) {
if ((prop = datas.province)) {
o = data[prop];
}
}
break;
case "district":
for (var prop in data) {
for (var value in data[prop]) {
if (value === datas.city) {
o = data[prop][value];
}
}
}
break;
}
res.end(JSON.stringify(o));
});
}
server.listen(4001, "10.9.72.220", function () {
console.log("服务器开启成功");
});