三级级联菜单(面向对象,,函数式编程,node,ajax,前后端数据交互)

三级联动效果,最终实现结果如下:
当点击河北切换省份,会产生联动,自动更新市级和县级, 当更新市级时,会自动更新县级

	页面下拉菜单产生变化时,会触发事件,从而通过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);
        }
    }
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值