三级地区切换(组件化开发)

1 篇文章 0 订阅
本文介绍了一个使用Express、Axios和MySQL数据库的三级联动地区选择组件的实现。通过导入自定义的LiItem和Address组件,实现了导航栏的动态加载,并通过axios从后台获取地址数据。组件中包含了事件监听、样式设置和数据交互,提供了省份、城市和地区的下拉选择功能。同时,展示了如何通过POST请求获取和展示地址数据。
摘要由CSDN通过智能技术生成

三级级联地区切换

说明:组件化开发,结合使用express框架搭建后台,axios传递数据,使用mysql数据库。

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>唯品会</title>
  <link rel="stylesheet" href="./css/public.css">
  <link rel="stylesheet" href="./css/index.css">
  <script src="./node_modules/axios/dist/axios.js"></script>
</head>
<body>
  <!-- nav -->
  <nav class="wrap">
    <div class="con">
      <div class="left">
      </div>
      <div class="right">
        <ul id="liTest"></ul>
      </div>
    </div>
  </nav>

  <script type="module">
    origin="localhost:3000";
    //nav liItem项
    import LiItem from "./js/LiItem.js";
    let arr=["请登录","注册","签到有礼","我的订单","我的特卖","会员俱乐部","客户服务","手机版","更多"];
    let slideDirecArr=["right",,,,"center","center","center","left","left"];
    let slideWidArr=[200,,,,,,,200,150];
    let slideHeiArr=[200,,,,80,80,80,200,150]
    arr.forEach((item,index)=>{
      let liItem=new LiItem(30,item,slideDirecArr[index],slideWidArr[index],slideHeiArr[index]);
      liItem.appendToUl("#liTest");
    });

    let login=LiItem.todoList.get("请登录");
    // console.dir(login);


    // nav 地址
    import Address from "./js/Address.js"
    let addressArr=[];
    axios.post("/getAddress1",{name:'北京',type:0}).then(res=>{
      // console.log(res)
      addressArr=res.data.data;
      // addressArr=addressArr.reduce((value,item)=>{
      //   value[value.length]=item.name;
      //   return value;
      // },[])
      let address=new Address(addressArr);
      address.appendTo("nav>.con>.left")
    })
    
    

    // axios.get(origin+"/getAddress").then(res=>{
    //   console.log(res)
    // })
  </script>
</body>
</html>
组件

import Component from "./Component.js"

export default class Address extends Component{
  data;
  prev;
  cprev;
  address;
  pos;
  bool=false;
  closeBool=false;
  constructor(_data){
    super();
    this.data=_data;
    // console.log(this.data)
    this.render();
    this.setStyle();
    // 500 280
  }
  render(){
    this.elem.innerHTML=`
      <div calss="head">
        <span>北京</span>
        <i></i>
      </div>
      <div calss="con">
        <p style="height:40px;line-height:40px;position:relative;">请选择你所在的地区<span style="height:40px;line-height:40px;display:block;position:absolute;right:0px;top:0px;font-size:20px;transform: rotateZ(45deg);cursor:pointer;">+</span></p>
        <ul>
          <li>省份</li>
          <li>城市</li>
          <li>地区</li>
        </ul>
        <div>
          ${(function(data){
            return data.map(item=>{
              return `<p style="width:93px;float:left;height:28px;line-height:28px;text-align:center;overflow:hidden;border:1px solid white;" data-index="${item.id}">${item.name}</p>`
            }).join("")
          })(this.data)}
        </div>
      </div>
    `
  }
  setStyle(){
    Object.assign(this.elem.style,{
      height:"30px",
      lineHeight:"30px",
      position:"relative"
    })
    Object.assign(this.elem.firstElementChild.style,{
      height:"28px",
      lineHeight:"28px",
      position:"relative",
      zIndex:"999",
      border:"1px solid #f5f5f5",
      borderBottom:"1px solid #f5f5f5",
      paddingRight:"25px",
      paddingLeft:"15px",
      cursor:"pointer"
    });
    Object.assign(this.elem.firstElementChild.children[1].style,{
      width:"0px",
      height:"0px",
      position:"absolute",
      top:"11px",
      right:"5px",
      borderWidth:"5px",
      borderColor:"#ccc transparent transparent",
      borderStyle:"solid dotted dotted"
    })
    //con 
    Object.assign(this.elem.children[1].style,{
      position:"absolute",
      top:"29px",
      left:"0px",
      zIndex:"99",
      width:"478px",
      height:"278px",
      padding:"10px",
      border:"1px solid #ccc",
      display:"none"
    })
    Object.assign(this.elem.children[1].children[1].style,{
      width:"100%",
      height:"29px",
      lineHeight:"28px",
      borderBottom:"1px solid #ccc",
    })
    Object.assign(this.elem.children[1].children[1].children[0].style,{
      height:"27px",
      border:"1px solid #ccc",
      borderWidth:"2px 1px 1px",
      borderTopColor:"#f10180",
      borderBottomColor:"white",
      float:"left",
      padding: "0px 15px",
      fontWeight:"700",
      color:"blank"
    })
    Object.assign(this.elem.children[1].children[1].children[1].style,{
      height:"28px",
      border:"1px solid #ccc",
      borderWidth:"1px",
      // borderBottomColor:"white",
      float:"left",
      padding: "0px 15px",
    })
    Object.assign(this.elem.children[1].children[1].children[2].style,{
      height:"28px",
      border:"1px solid #ccc",
      borderWidth:"1px",
      // borderBottomColor:"white",
      float:"left",
      padding: "0px 15px",
    })
    this.elem.addEventListener("click",e=>this.clickHandler(e));
    this.elem.children[1].firstElementChild.firstElementChild.addEventListener("click",e=>this.Handler(e));
    this.elem.children[1].children[1].children[0].addEventListener("click",e=>this.clickHandler2(e));
    this.elem.children[1].children[1].children[1].addEventListener("click",e=>this.clickHandler2(e));
    this.elem.children[1].children[1].children[2].addEventListener("click",e=>this.clickHandler2(e));
    this.prev=this.elem.children[1].children[1].children[0]
    this.elem.children[1].children[2].addEventListener("mouseover",e=>this.mouseHandler(e));
    this.elem.children[1].children[2].addEventListener("mouseout",e=>this.mouseHandler(e));

    this.elem.children[1].children[2].addEventListener("click",e=>this.clickHandler3(e));
    this.pos=this.elem.children[1].children[1].children[0];
    this.posi=0
  }
  Handler(){
    let evt=new Event("click");
    this.elem.dispatchEvent(evt);
  }
  clickHandler(e){
    if(e.target===this.elem.firstElementChild||e.target===this.elem.firstElementChild.children[0]||e.target===this.elem.firstElementChild.children[1]||e.target===this.elem.children[1].firstElementChild.firstElementChild||(e.target.parentElement===this.elem.children[1].children[2]&&this.closeBool)){
      if(!this.bool){
        Object.assign(this.elem.firstElementChild.style,{
          border:"1px solid #ccc",
          borderBottom:"1px solid white"
        });
        Object.assign(this.elem.children[1].style,{
          display:"block"
        })
        this.elem.style.backgroundColor="white"
        this.bool=true
      }else{
        Object.assign(this.elem.firstElementChild.style,{
          border:"1px solid #f5f5f5",
          borderBottom:"1px solid #f5f5f5"
        });
        Object.assign(this.elem.children[1].style,{
          display:"none"
        })
        this.elem.style.backgroundColor="#f5f5f5"
        this.bool=false
      }
    }
  }
  clickHandler2(e){
    if(e.target.nodeName!=="LI") return;
    switch(e.target.textContent){
      case "省份":
        this.pos=e.target;
        this.posi=0;
        break;
      case "城市":
          this.pos=e.target;
          this.posi=1;
          break;
      case "地区":
            this.pos=e.target;
            this.posi=2;
            break;
    }
    if(this.prev){
      Object.assign(this.prev.style,{
        height:"28px",
        border:"1px solid #ccc",
        borderWidth:"1px 1px 1px",
        fontWeight:"400",
        color:"#777"
      })
    }
    this.prev=e.target;
    Object.assign(this.prev.style,{
      height:"27px",
      border:"1px solid #ccc",
      borderWidth:"2px 1px 1px",
      borderTopColor:"#f10180",
      borderBottomColor:"white",
      fontWeight:"700",
      color:"blank"
    })
  }
  mouseHandler(e){
    if(e.target.nodeName!=="P") return;
    if(e.type==="mouseover"){
      e.target.style.color="#f10180"
      e.target.style.borderColor="#f10180"
    }else{
      e.target.style.color="#777"
      e.target.style.borderColor="white"
    }
  }
  clickHandler3(e){
    if(e.target.nodeName!=="P") return;
    let text=e.target.textContent;
    this.setText(text);
    this.toggleNext();
    let data={};
    data.name=e.target.textContent;
    data.id=e.target.dataset.index;
    // console.log(data)
    this.getData(data);
  }
  setText(text){
    this.elem.firstElementChild.firstElementChild.textContent=text;
  }
  toggleNext(){
    this.closeBool=false;
    let evt=new Event("click");
    let elem=this.pos;
    // console.dir(elem.nextElementSibling.parentElement)
    if(elem.nextElementSibling){
      elem.nextElementSibling.dispatchEvent(evt);
    }else{
      this.closeBool=true;
      this.elem.dispatchEvent(evt);
    }
  }
  getData(data){
    let i=this.posi
    let address;
    // console.log(this.posi)
    axios.post("/getAddress",{name:data.name,type:i,id:data.id}).then(res=>{
      // console.log(res)
      address=res.data.data;
      // console.log(address)
      this.setAddress(address)
    }).catch(err=>{
      this.elem.children[1].children[2].innerHTML="访问资源出错"
    })
  }
  setAddress(address){
    this.elem.children[1].children[2].innerHTML="";
    // console.log(address)
    let str=address.map(item=>{
      return `<p style="width:93px;float:left;height:28px;line-height:28px;text-align:center;overflow:hidden;border:1px solid white;" data-index="${item.id}">${item.name}</p>`
    }).join("")
    this.elem.children[1].children[2].innerHTML=str;
  }
}
基础组件

export default class Component{
  elem;
  constructor(){
    this.elem=this.createElem();
  }
  createElem(){
    let div=document.createElement("div");
    return div;
  }
  appendTo(parent){
    if(typeof parent === "string")parent=document.querySelector(parent);
    // console.log(parent)
    parent.appendChild(this.elem);
  }
}
接口代码

router.post("/getAddress1",(req,res,next)=>{
  // let data=req.body.data;
  
  db.select("*","provice","where 1").then(result=>{

    res.send(result)
  })
})

router.post("/getAddress",(req,res,next)=>{
  let data=req.body;
  console.log("11111",data)
  switch(data.type){
    case 1:
      db.select("*","city","where proviceid="+data.id).then(result=>{
        res.send(result)
      })
      break;
    case 2:
      db.select("*","regin","where cityid="+data.id).then(result=>{
        res.send(result)
      })
        break;
  }
  
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
系统包含项目的源码和搭建的详细文档,以及数据库脚本 系统功能模块(开发时可取舍) 1. 权限管理:点开二级菜单进入三级菜单显示 角色(基础权限)和按钮权限 角色(基础权限): 分角色组和角色,独立分配菜单权限和增删改查权限。 按钮权限: 给角色分配按钮权限。 2. 按钮管理:自定义按钮管理,维护按钮权限标识等 3. 菜单管理:无限级别自定义菜单,自定义菜单图标,业务菜单和系统菜单分离,菜单状态显示隐藏(递归处理) 4. 数据字典:无限级别,支持多级别无限分类。内设编号,排序等 5. 组织机构:无限级别,公司or部门管理 6. 在线管理:websocket技术,实时检测在线用户列表,统计在线人数,可强制用户下线 同一用户只能在一个客户端登录 7. 系统用户:对各个基本的用户增删改查,单发、群发站内信邮件短信,导入导出excel表格,批量删除 8. 会员管理:对前台用户管理,分配会员级别,到期时间,状态,联系信息等资料 9. 代码生成:生成完整的模块代码,并保留生成记录模版,可复用 (超强悍开发利器) 正向生成: 生成完整的模块,页面、处理类、service层、myabaits的xml 建表的sql脚本等 反向生成: 任意连接其它数据库(mysql、oracle、sqlserver),根据表反射生成本系统的模块 10. 性能监控:监控整个系统的性能,SQL监控,SQL防火墙,URL监控,SPRING监控,SESSION监控等 11. 接口测试:POST or GET 方式检测系统接口,参数加密,json返回结果,计算服务器响应时间 12. 发送邮件:单发,群发邮件 13. 置二维码:生成二维码图表保存到服务器 or 解析读取二维码内信息 14. 图表报表:柱状图、饼状图、折线图、各种图表大全 15. 地图工具:打开地图, 鼠标点击地图某位置获取经纬度坐标,根据经纬度计算两点距离 16. 打印测试:页面打印预览测试 17. 图片管理:对批量上传的图片统一管理 ,点击放大,可打开多个,自由切换,绚丽预览效果 18. 图片爬虫:输入某网址,爬出其图片显示在页面上,可以放大预览。可保存到服务器上,到图片管理里面 19. 站内信:收信箱和发信箱, websocket技术通讯技术做的及时收信提醒,可配置语音提示来信 20. 系统设置:修改系统名称,邮件服务器配置,短信账号设置,图片水印配置,微信配置 21. 及时聊天:打开聊天窗口,可群聊、一对一聊天 22. 表单构建:拖拽式快速自定义构建表单,组建元素丰富,有富文本、上传控件、下拉框等等 23. 主附结构:提供一个主表和明细表模块的例子(用本代码生成器生成的) 24. 员工管理:和组织机构部门管理,可以绑定登录系统用户,授权数据权限 -------------------------------------------------------------------------------------------------------------------------数据库管理 25. 数据库备份:可备份单表、整库,支持本地和远程数据库备份(java界面编程技术,socket编程技术) 26. 备份定时器:quartz 2.2 强大的任务调度,多线程备份数据库,任务启动关闭异步操作 27. 数据库还原:历史备份记录,还原数据库 or 单表 ,统计备份时间和文件大小 28. SQL编辑器:强大的SQL编辑器,支持编辑语句复杂查询语句,生成动态报表,可导出excel ------------------------------------------------------------------------------------------------------------------------- 菜单权限:分配给每个角色不同的菜单权限, 每个角色看到的菜单不同,无限级别菜单 按钮权限:独立分配不同的角色不同的功能权限,增删改查权限分配具体到不同的菜单,自定义按钮管理 支持多用户分权限管理后台, 权限具体到不同的菜单不同的按钮
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值