首页前端开发JavaScriptjs面向对象封装级联下拉菜单列表的实现步骤

js面向对象封装级联下拉菜单列表的实现步骤

时间2024-01-31 20:57:03发布访客分类JavaScript浏览204
导读:收集整理的这篇文章主要介绍了js面向对象封装级联下拉菜单列表的实现步骤,觉得挺不错的,现在分享给大家,也给大家做个参考。 本实例开发的级联下拉菜单是根据已有json数据创建的DOM元素。...
收集整理的这篇文章主要介绍了js面向对象封装级联下拉菜单列表的实现步骤,觉得挺不错的,现在分享给大家,也给大家做个参考。

本实例开发的级联下拉菜单是根据已有json数据创建的DOM元素。点击文本框后,显示一级菜单。如果菜单中包含子菜单,菜单右侧会有指示箭头。点击菜单之后,会再显示下一级菜单,以此类推。当菜单下无子菜单时,选择菜单后会在文本框中显示。

打开后的级联菜单效果如图所示:

使用实例中封装好的插件,只需要有一个input元素,即可通过插件自动生成级联下拉菜单,htML代码如下所示:

 div style="margin-top:100px;
    text-align:center;
    ">
      input tyPE="text" id="input">
     /div>
    

接下来看下具体封装的js代码怎么实现。

1. 声明级联菜单的构造函数

构造函数需要传入一个文本框元素和菜单关联数据两个参数。

 //elem为文本框,data为菜单关联数据 function CasCADeMenu(elem,data){
 }
    

2. 在构造函数中创建级联菜单相关元素,并放到页面中,具体代码如下:

function CascadeMenu(elem,data){
      //获取文本框  this.einput = elem;
      //设置文本框为只读  this.eInput.setattribute('readonly',true);
      //设置文本框提示  this.eInput.placeholder = '请选择';
      //获取文本框父元素  VAR eInputParent = this.eInput.parentNode;
      //创建级联菜单容器  this.eCascade = document.createElement('div');
      this.eCascade.classname = 'cascade_container';
      //创建菜单下拉列表容器  this.eCascadeInto = document.createElement('div');
      this.eCascadeInto.className = 'cascade_into';
      //下拉列表容器默认隐藏  this.eCascadeInto.style.display = 'none';
      //将各个元素放到页面中  this.eCascade.appendChild(this.eInput);
      this.eCascade.appendChild(this.eCascadeInto);
      eInputParent.appendChild(this.eCascade);
      //获取菜单数据  this.aData = data;
      //记录已选择的菜单数据  this.aSelected = [];
      //菜单打开状态,默认为false,表示隐藏  this.bShow = false;
 }
    

3. 在文本框上绑定点击事件,生成级联下拉菜单

刚才已经把需要的元素都放到了页面中,现在可以通过点击文本框显示和隐藏级联菜单元素;
在显示级联菜单元素时,应该要通过数据生成级联下拉菜单。
因为每次点击都需要生成,所以可以在构造函数的原型上添加一个方法。如下所示: 

function CascadeMenu(elem,data){
      /*…*/  this.eInput.addEventListener('click',()=>
{
   //判断菜单打开状态   if(this.bShow){
         //如果已打开,则隐藏菜单    this.eCascadeInto.style.display = 'none';
        //修改菜单打开状态    this.bShow = false;
   }
else{
        //显示级联菜单元素    this.eCascadeInto.style.display = 'none';
        //保存已选择的菜单数据    this.aSelected = this.eInput.value.splIT('>
    ');
        //生成级联菜单    this.generateMenu();
   }
  }
    );
 }
 //根据数据生成级联菜单 CascadeMenu.PRototype.generateMenu = function(){
      //在fnCreatHTML调用实例对象需要声明一个变量指向this  var _self = this;
  //因为不确定子菜单有多少组,所以需要声明一个函数来递归调用  //data:传入数据,step:当前级别  function fnCreatHTML(data,step){
       //用于存储子菜单数据   var aChildArr = null;
       //生成菜单DOM的字符串   var sHTML = 'ul>
    ';
       //循环数据   for(let i=0;
    idata.length;
i++){
    //判断如果有子菜单,添加child的class,用于显示菜单右侧箭头    if(data[i].child){
      //判断是否是当前选择,如果是,加上cur class,并且存储子菜单数据     if(data[i].name==this.aSelected[step]){
          aChildArr = data[i].child;
          sHTML += 'li class="child cur" data-po="'+step+'">
    ';
     }
else{
          sHTML += 'li class="child" data-po="'+step+'">
    ';
     }
    }
else{
          //如果没有子菜单,直接加到菜单列表中     sHTML += data[i].name == this.aSelected[step]?                  'li class="cur" data-po="'+step+'">
    ':                  'li data-po="'+step+'">
    ';
    }
        //添加菜单名称    sHTML += data[i].name;
        //结束当前菜单    sHTML += '/li>
    ';
   }
       sHTML += '/ul>
    ';
       //如果已选择多个菜单,递归调用函数,生成子菜单   if(this.aSelected.length>
step+1){
        sHTML += fnCreatHTML(aChildArr,step+1);
   }
       return sHTML;
  }
      this.eCascadeInto.innerHTML = fnCreatHTML(this.aData,0);
 }
    

4. 菜单上绑定事件,用于选择菜单

级联菜单有两种类型,一种是有下级菜单的,点击时显示下级菜单;
一种是没有下级菜单的,点击时直接选择菜单并在文本框中按级别显示所选择的菜单。代码如下所示:

function CascadeMenu(elem,data){
      /*…*/  //利用事件委托选择菜单  this.eCascadeInto.addEventListener('click',(event)=>
{
       //获取菜单   var eTarget = event.target;
       //获取选择的级别   var po = +eTarget.dataset.po;
       //删除当前选择级后面的数据   this.aSelected.splice(po+1,this.aSelected.length-(po+1));
       //修改当前选择数据   this.aSelected[po] = eTarget.innerHTML;
   //判断是否有子菜单   if(eTarget.className.indexOf('child')==-1){
     //没有子菜单直接选择    this.eInput.value = this.aSelected.join('>
    ');
        this.eCascadeInto.style.display = 'none';
        this.bShow = false;
   }
else{
     //有子菜单显示下一级    //重新生成DOM元素,数组中增加空字符串用于显示下一级    this.aSelected.push('')    //重新生成级联菜单    this.generateMenu();
   }
    }
    );
 }
    

5. 在页面空白处点击时,隐藏菜单

现在只能在文本框上点击显示和隐藏菜单。一般来说任何打开的弹框,都希望在弹框以外的位置可以关闭掉。这样需要修改一下文本框上的点击事件函数:当打开菜单时,要在document元素上绑定点击事件,用于关闭菜单;当隐藏菜单时,需要取消document上绑定的点击事件。如下所示:

function CascadeMenu(elem,data){
      /*…*/  this.eInput.addEventListener('click',()=>
{
   //判断菜单打开状态   if(this.bShow){
         //如果已打开,则隐藏菜单    this.eCascadeInto.style.display = 'none';
        //修改菜单打开状态    this.bShow = false;
        //取消document上的事件    document.onclick = null;
   }
else{
        //显示级联菜单元素    this.eCascadeInto.style.display = 'none';
        //保存已选择的菜单数据    this.aSelected = this.eInput.value.split('>
    ');
        //生成级联菜单    this.generateMenu();
        document.onclick = () =>
 {
         //隐藏菜单     this.eCascadeInto.style.display = 'none';
         //修改菜单打开状态     this.bShow = false;
         //取消document上的事件     document.onclick = null;
    }
   }
  }
    );
      //阻止冒泡  this.eCascade.addEventListener('click',(event)=>
{
       event.stopPropagation();
  }
    );
  /*…*/ }
    

6. 最后,准备好数据,调用构造函数,生成级联下拉菜单,如下所示:

var JSON = [  {
   "name":"北京市","id":"110000","child":[    {
"name":"市辖区","id":"110100","child":[     {
"name":"东城区","id":"110101","child":null}
,{
"name":"西城区","id":"110102","child":null}
,{
"name":"朝阳区","id":"110105","child":null}
,{
"name":"丰台区","id":"110106","child":null}
,{
"name":"石景山区","id":"110107","child":null}
,{
"name":"海淀区","id":"110108","child":null}
,{
"name":"门头沟区","id":"110109","child":null}
,{
"name":"房山区","id":"110111","child":null}
,{
"name":"通州区","id":"110112","child":null}
,{
"name":"顺义区","id":"110113","child":null}
,{
"name":"昌平区","id":"110114","child":null}
,{
"name":"大兴区","id":"110115","child":null}
,{
"name":"怀柔区","id":"110116","child":null}
,{
"name":"平谷区","id":"110117","child":null}
,{
"name":"密云区","id":"110118","child":null}
,{
"name":"延庆区","id":"110119","child":null}
]    }
,    {
"name":"北京市","id":"110000","child":null}
   ]  }
,  {
   "name":"河北省","id":"130000","child":[    {
"name":"石家庄市","id":"130100","child":[     {
"name":"市辖区","id":"130101","child":null}
,{
"name":"长安区","id":"130102","child":null}
,{
"name":"桥西区","id":"130104","child":null}
,{
"name":"新华区","id":"130105","child":null}
,{
"name":"井陉矿区","id":"130107","child":null}
,{
"name":"裕华区","id":"130108","child":null}
,{
"name":"藁城区","id":"130109","child":null}
,{
"name":"鹿泉区","id":"130110","child":null}
,{
"name":"栾城区","id":"130111","child":null}
,{
"name":"井陉县","id":"130121","child":null}
,{
"name":"正定县","id":"130123","child":null}
,{
"name":"行唐县","id":"130125","child":null}
,{
"name":"灵寿县","id":"130126","child":null}
,{
"name":"高邑县","id":"130127","child":null}
,{
"name":"深泽县","id":"130128","child":null}
,{
"name":"赞皇县","id":"130129","child":null}
,{
"name":"无极县","id":"130130","child":null}
,{
"name":"平山县","id":"130131","child":null}
,{
"name":"元氏县","id":"130132","child":null}
,{
"name":"赵县","id":"130133","child":null}
,{
"name":"晋州市","id":"130183","child":null}
,{
"name":"新乐市","id":"130184","child":null}
]    }
,    {
"name":"唐山市","id":"130200","child":[     {
"name":"市辖区","id":"130201","child":null}
,{
"name":"路南区","id":"130202","child":null}
,{
"name":"路北区","id":"130203","child":null}
,{
"name":"古冶区","id":"130204","child":null}
,{
"name":"开平区","id":"130205","child":null}
,{
"name":"丰南区","id":"130207","child":null}
,{
"name":"丰润区","id":"130208","child":null}
,{
"name":"曹妃甸区","id":"130209","child":null}
,{
"name":"滦县","id":"130223","child":null}
,{
"name":"滦南县","id":"130224","child":null}
,{
"name":"乐亭县","id":"130225","child":null}
,{
"name":"迁西县","id":"130227","child":null}
,{
"name":"玉田县","id":"130229","child":null}
,{
"name":"遵化市","id":"130281","child":null}
,{
"name":"迁安市","id":"130283","child":null}
]    }
,    {
"name":"秦皇岛市","id":"130300","child":[     {
"name":"市辖区","id":"130301","child":null}
,{
"name":"海港区","id":"130302","child":null}
,{
"name":"山海关区","id":"130303","child":null}
,{
"name":"北戴河区","id":"130304","child":null}
,{
"name":"抚宁区","id":"130306","child":null}
,{
"name":"青龙满族自治县","id":"130321","child":null}
,{
"name":"昌黎县","id":"130322","child":null}
,{
"name":"卢龙县","id":"130324","child":null}
]    }
,    {
"name":"邯郸市","id":"130400","child":[     {
"name":"市辖区","id":"130401","child":null}
,{
"name":"邯山区","id":"130402","child":null}
,{
"name":"丛台区","id":"130403","child":null}
,{
"name":"复兴区","id":"130404","child":null}
,{
"name":"峰峰矿区","id":"130406","child":null}
,{
"name":"邯郸县","id":"130421","child":null}
,{
"name":"临漳县","id":"130423","child":null}
,{
"name":"成安县","id":"130424","child":null}
,{
"name":"大名县","id":"130425","child":null}
,{
"name":"涉县","id":"130426","child":null}
,{
"name":"磁县","id":"130427","child":null}
,{
"name":"肥乡县","id":"130428","child":null}
,{
"name":"永年县","id":"130429","child":null}
,{
"name":"邱县","id":"130430","child":null}
,{
"name":"鸡泽县","id":"130431","child":null}
,{
"name":"广平县","id":"130432","child":null}
,{
"name":"馆陶县","id":"130433","child":null}
,{
"name":"魏县","id":"130434","child":null}
,{
"name":"曲周县","id":"130435","child":null}
,{
"name":"武安市","id":"130481","child":null}
]    }
   ]  }
,  {
   "name":"湖南省","id":"430000","child":[    {
"name":"长沙市","id":"430100","child":[     {
"name":"市辖区","id":"430101","child":null}
,{
"name":"芙蓉区","id":"430102","child":null}
,{
"name":"天心区","id":"430103","child":null}
,{
"name":"岳麓区","id":"430104","child":null}
,{
"name":"开福区","id":"430105","child":null}
,{
"name":"雨花区","id":"430111","child":null}
,{
"name":"望城区","id":"430112","child":null}
,{
"name":"长沙县","id":"430121","child":null}
,{
"name":"宁乡县","id":"430124","child":null}
,{
"name":"浏阳市","id":"430181","child":null}
]    }
,    {
"name":"株洲市","id":"430200","child":[     {
"name":"市辖区","id":"430201","child":null}
,{
"name":"荷塘区","id":"430202","child":null}
,{
"name":"芦淞区","id":"430203","child":null}
,{
"name":"石峰区","id":"430204","child":null}
,{
"name":"天元区","id":"430211","child":null}
,{
"name":"株洲县","id":"430221","child":null}
,{
"name":"攸县","id":"430223","child":null}
,{
"name":"茶陵县","id":"430224","child":null}
,{
"name":"炎陵县","id":"430225","child":null}
,{
"name":"醴陵市","id":"430281","child":null}
]    }
,    {
"name":"湘潭市","id":"430300","child":[     {
"name":"市辖区","id":"430301","child":null}
,{
"name":"雨湖区","id":"430302","child":null}
,{
"name":"岳塘区","id":"430304","child":null}
,{
"name":"湘潭县","id":"430321","child":null}
,{
"name":"湘乡市","id":"430381","child":null}
,{
"name":"韶山市","id":"430382","child":null}
]    }
,    {
"name":"衡阳市","id":"430400","child":[     {
"name":"市辖区","id":"430401","child":null}
,{
"name":"珠晖区","id":"430405","child":null}
,{
"name":"雁峰区","id":"430406","child":null}
,{
"name":"石鼓区","id":"430407","child":null}
,{
"name":"蒸湘区","id":"430408","child":null}
,{
"name":"南岳区","id":"430412","child":null}
,{
"name":"衡阳县","id":"430421","child":null}
,{
"name":"衡南县","id":"430422","child":[      {
"name":"三塘镇",id:"430422",child:null}
,{
"name":"车江镇",id:"430422",child:null}
     ]}
,{
"name":"衡山县","id":"430423","child":null}
,{
"name":"衡东县","id":"430424","child":null}
,{
"name":"祁东县","id":"430426","child":null}
,{
"name":"耒阳市","id":"430481","child":null}
,{
"name":"常宁市","id":"430482","child":null}
]    }
   ]  }
,  {
   "name":"广东省","id":"440000","child":[    {
"name":"广州市","id":"440100","child":[     {
"name":"市辖区","id":"440101","child":null}
,{
"name":"荔湾区","id":"440103","child":null}
,{
"name":"越秀区","id":"440104","child":null}
,{
"name":"海珠区","id":"440105","child":null}
,{
"name":"天河区","id":"440106","child":null}
,{
"name":"白云区","id":"440111","child":null}
,{
"name":"黄埔区","id":"440112","child":null}
,{
"name":"番禺区","id":"440113","child":null}
,{
"name":"花都区","id":"440114","child":null}
,{
"name":"南沙区","id":"440115","child":null}
,{
"name":"从化区","id":"440117","child":null}
,{
"name":"增城区","id":"440118","child":null}
]    }
,    {
"name":"韶关市","id":"440200","child":[     {
"name":"市辖区","id":"440201","child":null}
,{
"name":"武江区","id":"440203","child":null}
,{
"name":"浈江区","id":"440204","child":null}
,{
"name":"曲江区","id":"440205","child":null}
,{
"name":"始兴县","id":"440222","child":null}
,{
"name":"仁化县","id":"440224","child":null}
,{
"name":"翁源县","id":"440229","child":null}
,{
"name":"乳源瑶族自治县","id":"440232","child":null}
,{
"name":"新丰县","id":"440233","child":null}
,{
"name":"乐昌市","id":"440281","child":null}
,{
"name":"南雄市","id":"440282","child":null}
]    }
,    {
"name":"深圳市","id":"440300","child":[     {
"name":"市辖区","id":"440301","child":null}
,{
"name":"罗湖区","id":"440303","child":null}
,{
"name":"福田区","id":"440304","child":null}
,{
"name":"南山区","id":"440305","child":null}
,{
"name":"宝安区","id":"440306","child":null}
,{
"name":"龙岗区","id":"440307","child":null}
,{
"name":"盐田区","id":"440308","child":null}
]    }
,    {
"name":"珠海市","id":"440400","child":[     {
"name":"市辖区","id":"440401","child":null}
,{
"name":"香洲区","id":"440402","child":null}
,{
"name":"斗门区","id":"440403","child":null}
,{
"name":"金湾区","id":"440404","child":null}
]    }
   ]  }
,  {
   "name":"南沙群岛","id":"900001","child":null  }
     ];
     var eText = document.getElementById('input');
     new CascadeMenu(eText,json);
    

一个封装好的js级联下拉功能就完成了,可以根据图片自己编写css样式以达到需要的效果。

以上就是js面向对象封装级联下拉菜单列表的实现步骤的详细内容,更多关于js 封装下拉菜单的资料请关注其它相关文章!

您可能感兴趣的文章:
  • JavaScript实现HTML导航栏下拉菜单
  • JavaScript实现网页下拉菜单效果
  • Vue.js下拉菜单组件使用方法详解
  • js 下拉菜单点击旁边收起实现(踩坑记)
  • 浅谈Vue.js中如何实现自定义下拉菜单指令
  • js实现按钮开关单机下拉菜单效果
  • js动态设置select下拉菜单的默认选中项实例
  • 纯JS实现出生日期[年月日]下拉菜单效果
  • JS实现点击下拉菜单把选择的内容同步到input输入框内的实例
  • js阻止默认右键的下拉菜单方法

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

js面向对象

若转载请注明出处: js面向对象封装级联下拉菜单列表的实现步骤
本文地址: https://pptw.com/jishu/594469.html
原生js 实现表单验证功能 Handtrack.js库实现实时监测手部运动(推荐)

游客 回复需填写必要信息