原生JS通过前后端通信,实现三级级联菜单

实现效果三级菜单联动效果

实现思路

  1. 开始设置默认值,获取最初的菜单状态
  2. 每次点击向后端通信,获取点击后的相应省/市/区的数据
  3. 获取到相应的数据后,再次重新渲染页面

项目接口文件

URL: http://10.9.72.246:4010

Method: POST

DataType:

请求消息: QueryString
相应消息: JSON

接口名称

  1. http http://10.9.72.246/province
  2. http http://10.9.72.246/city
  3. http http://10.9.72.246/country

获取省级数据

接口名:province
请求: 无参数或者省级名称
响应:{
“北京”:{
“北京”: [“东城区”, “西城区”, “崇文区”, “宣武区”, “朝阳区”, “丰台区”, “石景山区”, “海淀区”, “门头沟区”, “房山区”, "通州区"能, “顺义区”, “昌平区”, “大兴区”, “平谷区”, “怀柔区”, “密云县”, “延庆县”, “其他”]
},
}

}

市级数据

接口名:city
请求: province = “河北” 省级名称
响应:{
“石家庄”,
“秦皇岛”,
“保定”,

}

区级数据

接口名:country
请求: {
province: “河北”,
city: “石家庄”
}
响应: [
“长安区”, “桥东区”, “桥西区”, “新华区”, “井陉矿区”, “裕华区”, “井陉县”, “正定县”, “栾城县”, “行唐县”, “灵寿县”, “高邑县”, “深泽县”, “赞皇县”, “无极县”, “平山县”, “元氏县”, “赵县”, “辛集市”, “藁城市”, “晋州市”, “新乐市”, “鹿泉市”, “其他”
]

服务端代码
var data = require("./data.js");
var http = require("http");
var querystring = require("querystring");
var req, res;

var server = http.createServer(function (_req, _res) {
	var reqData = "";
	req = _req;
	res = _res;
	res.writeHead(200, {
		"content-type": "text/html;charset=utf-8",
		"Access-Control-Allow-Origin": "*",
		"Access-Control-Allow-Headers": "*",
	});

	req.on("data", function (_data) {
		reqData += _data;
	});

	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();
			reqData = req.url.includes("?") ? req.url.split("?")[1] : "";
		}
		try {
			reqDate = JSON.parse(data);
		} catch (e) {
			reqData = data ? querystring.parse(reqData) : {};
		}
		var o = {};
		switch (type) {
			case "province":
				if (JSON.stringify(reqData) === "{}") {
					for (var prop in data) {
						o[prop] = prop;
					}
				} else {
					o[reqData.province] = data[reqData.province];
				}
				break;
			case "city":
				for (var province in data) {
					if (province === reqData.province) {
						o = data[province];
					}
				}
				break;
			case "country":
				for (var province in data) {
					for (var city in data[province]) {
						if (city === reqData.city) {
							o = data[province][city];
						}
					}
				}
				break;
		}
		res.end(JSON.stringify(o));
	});
});

server.listen(4010, "10.9.72.246", function () {
	console.log("服务已经开启!");
});

生成菜单代码
export default class ThreeLevel {
	data;
	elem;
	province;
	city;
	courty;
	select;
	p;
	c;
	pre = 0;
	constructor(_data) {
		this.data = _data;
		this.elem = document.createElement("div");
		this.province = document.querySelector(".province");
		this.city = document.querySelector(".city");
		this.courty = document.querySelector(".country");
		this.createOptions(_data, this.province);
	}

	createOptions(_data, _select) {
		var data = _data;

		var df = document.createDocumentFragment();

		if (_select.options.length) {
      _select.removeEventListener("change", this.changeHandler);
      _select.removeEventListener("mousedown", this.mouseHandler);
      _select.removeEventListener("mouseout", this.mouseHandler);
			_select.options.length = 0;
		}

		if ({}.toString.call(data).includes("Object")) {
			var bool = false;
			for (var prop in data) {
				var option = document.createElement("option");
				if (!bool) {
					option.setAttribute("selected", "selected");
					bool = true;
				}
				option.textContent = prop;
				df.appendChild(option);
			}
			_select.addEventListener("change", (e) => this.changeHandler(e));
			_select.addEventListener("mousedown", (e) => this.mouseHandler(e));
			_select.addEventListener("mouseout", (e) => this.mouseHandler(e));
		} else {
			for (var i = 0; i < data.length; i++) {
				var option = document.createElement("option");
				option.textContent = data[i];
				df.appendChild(option);
			}
		}
		_select.appendChild(df);
	}

	changeHandler(e) {
		// console.log("start");
		var select = e.currentTarget;

    var index = select.selectedIndex;
    console.log(index);
		var txt = select.options[index].value;
		if (select.className === "province") {
			var data = this.data[txt];
			this.p = txt;
			this.c = "";
			this.createOptions(data, this.city);
		} else if (select.className === "city") {
			this.c = txt;
			var data = this.data[this.p][this.c];
			this.createOptions(data, this.courty);
		}
	}

	mouseHandler(e) {
		var select = e.currentTarget;
		// console.log(select);
		if (e.type === "mousedown") {
      console.log("second");
			this.pre = select.selectedIndex;
			// console.log(this.pre);
			select.selectedIndex = -1;
		} else if (e.type === "mouseout") {
			var index = select.selectedIndex;
			console.log(this.pre);
			if (index == -1) {
				select.selectedIndex = this.pre;
			}
		}
	}
}

前端代码
<!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>
  <script type=module>
    import ThreeLevel from "./js/ThreeLevel.js";
    var threeLevel = new ThreeLevel();
    threeLevel.appendTo("body");
  </script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值