本文实例为大家分享了JavaScript+node实现三级联动菜单的具体代码,供大家参考,具体内容如下
项目分析 1、效果 2、前端=>面向对象
=>首先分析下拉结构,构造相应的结构和样式
=>绑定事件,点击,鼠标滑过等
=>导入写好的 js 文件 构造菜单项、
=>使用ajax请求服务端 获取数据
=>用每次获取的数据动态生成页面结构
3、服务端=>接口文档(定义接口,服务地址,端口}
=>存储数据
=>创建服务器
=>接收前端的ajax请求,响应数据
代码 1、面向对象代码export default class Select{
//添加css样式
static addCSS(selector,style,title){
if(title===undefined) title="xietian";
var arr=Array.from(document.styleSheets);
var styleSheet=arr.reduce(function(value,item){
if(item.title===title)return item;
return value;
},null);
if(!styleSheet){
var s=document.createElement("style");
s.title=title;
document.head.appendChild(s);
styleSheet=document.styleSheets[document.styleSheets.length-1];
}
var str="";
for(var prop in style){
str+=prop.replace(/[A-Z]/g,function(value){
return "-"+value.toLowerCase();
})+":"+(typeof style[prop]==="number" ? style[prop]+"px" : style[prop])+";";
}
if(styleSheet.addRule){
styleSheet.addRule(selector,str,styleSheet.cssRules.length);
}else{
styleSheet.insertRule(selector+"{ "+str+" }",styleSheet.cssRules.length);
}
}
//定义全局变量
button;
ul;
class;
constructor(parent,_class) {
// this.id = _id;
this.class = _class;
this.elem = this.createEle();
this.appendTo(parent);
}
//创建元素
createEle() {
const div = document.createElement('div');
div.className = "dropdown " + this.class;
this.button = document.createElement('button');
this.button.className = "btn btn-default dropdown-toggle";
this.button.addEventListener('click',e=>this.clickHander(e))
this.content = document.createElement('span');
this.content.innerText = "请选择";
const carte = document.createElement('span');
this.content.className = 'content';
carte.className = 'carte';
this.button.appendChild(this.content);
this.button.appendChild(carte);
this.ul = document.createElement('ul');
this.ul.className = "dropdown-menu";
this.button.appendChild(this.ul);
div.appendChild(this.button)
return div;
}
//添加点击事件
clickHander(e) {
this.ul.classList.toggle('on');
}
//增加li
addli(list) {
if(!list) return;
const frg = document.createDocumentFragment();
list.forEach(item=>{
const li = document.createElement('li');
li.innerHTML = item;
li.addEventListener('click',e=>this.liHandler(e));
frg.appendChild(li);
})
this.ul.appendChild(frg);
}
//给li添加的点击事件
liHandler(e) {
this.content.innerHTML = e.target.innerText;
}
//添加css样式
addCSS() {
Select.addCSS(".dropdown",{
position: "relative",
boxSizing: "border-box",
width: "8.33333333%",
display:"inline-block",
minHeight: "1px",
paddingRight: "15px",
paddingLeft: "15px",
fontSize: "14px",
lineHeight: "1.42857143",
color: "#333333",
})
Select.addCSS(".btn",{
display:'inlineBlock',
marginBottom:'0',
outline:"none",
fontWeight:'normal',
textAlign:'center',
whiteSpace:'nowrap',
verticalAlign:'middle',
touchAction:'manipulation',
cursor:'pointer',
backgroundImage:'none',
border:'1px solid transparent',
padding:'6px 12px',
fontSize:'14px',
lineHeight:'1.42857143',
borderRadius:'4px',
userSelect:'none',
})
Select.addCSS(".btn-default",{
color:'#333',
backgroundColor:'#fff',
borderColor:'#ccc',
})
Select.addCSS(".btn-default:hover",{
color:'#333',
backgroundColor:'#e6e6e6',
borderColor:'#adadad',
})
Select.addCSS(".carte",{
display:'inline-block',
width:'0',
marginLeft: "0",
height:'0',
verticalAlign:'middle',
borderTop:'4px dashed',
borderRight:'4px solid transparent',
borderLeft:'4px solid transparent',
})
Select.addCSS(".dropdown-menu",{
position:'absolute',
top:'100%',
left:'15px',
height:'200px',
overflowY:'scroll',
zIndex:'1000',
display:'none',
float:'left',
minWidth:'83px',
padding:'5px 0',
margin:'2px 0 0',
fontSize:'14px',
textAlign:'left',
listStyle:'none',
backgroundColor:'#fff',
backgroundClip:'paddingBox',
border:'1px solid #ccc',
border:'1px solid rgba(0, 0, 0, 0.15)',
borderRadius:'4px',
boxShadow:'0 6px 12px rgba(0, 0, 0, 0.175)',
})
Select.addCSS(".on", {
display:"block!important",
})
Select.addCSS('li',{
textAlign:"center",
})
Select.addCSS('li:hover',{
backgroundColor:'#e6e6e6',
})
}
//添加到html结构中的位置
appendTo(parent) {
if(typeof parent == 'string') parent=document.querySelector(parent);
parent.appendChild(this.elem);
this.addCSS();
}
}
2、向服务器请求ajax
<script type="module">
import Select from "./select.js";
// var list = ["北京","上海","广州","深圳","武汉"];
let citylist,provincelist,countylist,province_content,content_county;
var sel_p = new Select('.box','province');
ajax("city.json",(res)=>{
provincelist = Object.keys(res);
sel_p.addli(provincelist);
sel_p.elem.addEventListener('click',clickHandler)
province_content = document.querySelector('.province .content');
county()
})
var sel_c = new Select('.box','city');
function clickHandler(e) {
if(e.target.constructor!== HTMLLIElement) return;
ajax(`http://10.9.72.252:4001/province/?province=${e.target.innerText.trim()}`,function(res){
citylist = Object.keys(res.city)
sel_c.addli(citylist);
const province = document.querySelector('.province ul');
province.addEventListener('click',cityHandler);
})
}
function cityHandler(e) {
const content_city = document.querySelector('.city .content');
const li = document.querySelectorAll('.city li');
const content_county = document.querySelector('.county .content');
content_county.innerText=content_city.innerText = "请选择";
li.forEach(item=>{
item.remove();
})
}
//获取区县数据
function county() {
var sel_conuty = new Select('.box','county');
sel_c.elem.addEventListener('click',e=>{
if(e.target.constructor!== HTMLLIElement) return;
ajax(`http://10.9.72.252:4001/city/?province=${province_content.innerText.trim()}&city=${e.target.innerText.trim()}`,function(res){
// console.log(res);
countylist =res.county
sel_conuty.addli(countylist);
const city = document.querySelector('.city ul');
city.addEventListener('click',countyHandler);
})
})
}
function countyHandler(e) {
const lis = document.querySelectorAll('.county li');
const content_coun = document.querySelector('.county .content');
content_coun.innerText = "请选择";
lis.forEach(item=>{
item.remove();
})
}
//封装一个简单的
function ajax(url, fn) {
// XMLHttpRequest对象用于在后台与服务器交换数据
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true)
xhr.onreadystatechange = function () {
if(xhr.readyState == 4 && xhr.status ==200) {
//从服务器获得数据
fn.call(this, JSON.parse(xhr.responseText));
}
};
//发送数据
xhr.send();
}
</script>
3、服务端
const http = require('http');
const querystring= require('querystring');
const city = require("../city.json");
const server = http.createServer(function(req, res) {
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 () {
// type是接口名称
console.log(req.url);
var type=req.url.trim().split("?")[0].replace(/\//g,"");
console.log(type);
if(req.method.toLowerCase()==="get"){
if(req.url.includes("favicon.ico")) return res.end();//如果get请求的是图标直接返回空跳出
// 如果是get请求,就从url中重新获取数据存入data变量
data=req.url.includes("?") ? req.url.split("?")[1] : "";
}
// 首先判断是否可以通过JSON解析,如果通过JSON直接转换,如果不能就是querystring解析
try{
data=JSON.parse(data);
}catch(e){
data=data ? querystring.parse(data) : {};
console.log(data);
}
let o = {}
switch(type){
case 'province':
o = {};
o.city = obj[data.province];
break;
case 'city':
o.city = obj[data.province];
o.county = o.city[data.city];
break;
}
res.write(JSON.stringify(o));
res.end();
})
})
//监听4001端口
server.listen(4001,"你的地址",function() {
console.log("服务器开启成功^_^");
})