• 售前

  • 售后

热门帖子
入门百科

原生js实现下拉框选择组件

[复制链接]
务川冷泉水鱼庄 显示全部楼层 发表于 2021-10-25 19:24:04 |阅读模式 打印 上一主题 下一主题
本文实例为各人分享了js实现下拉框选择组件的详细代码,供各人参考,详细内容如下
功能需求:
1、点击div后,div表现聚焦状态,同时表现下拉框内容;
2、选择儿童人数后,如果儿童人数大于0,在下方出现对应的儿童年事选择框数量;
3、成大家数的选择范围是1-7,儿童人数的选择范围是0-4,儿童年事的选择范围是<1、1-17;
4、点击确认按钮后,将选择好的成大家数和儿童人数表如今最上方的div内;
5、可以控制选择框是否可点击;
6、当表现一个ul列表时,点击另一个ul列表,将上一个ul列表隐蔽;
7、点击隐蔽框内除绑定事件元素外,将正在表现的ul列表隐蔽;
8、点击页面中恣意空缺位置,将表现的下拉框内容整体隐蔽;

下拉框不可操纵时的表现状态:

下拉框可操纵时:

选择儿童人数后,下方主动出现对应数量的儿童年事选择框:

点击确认按钮后,将效果表如今是上方的div内:

刚开始的想法是对select、ul下拉列表、btn按钮分别举行事件监听,别的还要有当点击下拉框内别的位置时,ul下拉列表隐蔽、当点击body时整个下拉框内包庇蔽。监听事件过多,而且事件冒泡也会影响事件的实行,导致某些事件会出实际行多次的情况。
儿童年事的选择框是根据儿童的人数来天生的,有几个儿童,就有几个年事选择框。这种情况下,年事的选择框肯定是动态创建的,无法针对年事的select举行事件监听,只能接纳事件委托的形式,所以末了把对select、ul下拉列表、btn按钮的点击事件,另有当点击container内别的位置时,ul下拉列表隐蔽。全部委托给了dropDownContainer元素。
下面附上代码
html结构代码:
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.   <meta charset="UTF-8">
  5.   <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.   <title>select</title>
  7. </head>
  8. <body>
  9.   <script type="module">
  10.     import Main from './js/Main.js';
  11.     //参数为false时,选择框不可点击;为true时,选择框可使用
  12.     let main=new Main(true);
  13.     main.appendTo("body");
  14.   </script>
  15. </body>
  16. </html>
复制代码
Main.js文件:
  1. import Utils from './Utils.js';
  2. export default class Main{
  3.   static styles=false;
  4.   listPrep;
  5.   constructor(state){
  6.     //state控制下拉框是否可点击
  7.     this.state=state;
  8.     this.elem=this.createE();
  9.   }
  10.   createE(){
  11.     if(this.elem) return this.elem;
  12.     let div=Utils.createE("div");
  13.     div.className="guestsNum";
  14.     div.innerHTML=`<span>人数未定</span><i></i>
  15.     <div class="dropDownContainer none" id="dropDownContainer">
  16.       <div class="dropDownItem clearfix">
  17.         <span>每间</span>
  18.         <div class="dropDownSelect">
  19.           <div class="dropDownCont"><span id="adultNum">2 成人</span><i></i></div>
  20.           <ul class="dropDownList" tag="adult">${this.setDropDownList("adult")}</ul>
  21.         </div>
  22.         <div class="dropDownSelect">
  23.           <div class="dropDownCont"><span id="childrenNum">0 儿童</span><i></i></div>
  24.           <ul class="dropDownList" tag="children"><li>0</li>${this.setDropDownList("children")}</ul>
  25.         </div>
  26.       </div>
  27.       <div class="dropDownItem clearfix none" id="ItemAge"></div>
  28.       <div class="dropDownBottom clearfix">
  29.         ${this.state?'':'<em class="dropDownTips">请优先选择日期,以便查询实时价格。</em>'}
  30.         ${this.state?'<a class="dropDownBtn" id="dropDownBtn" href="javascript:void(0)" rel="external nofollow" rel="external nofollow" >确认</a>':'<a class="dropDownBtn disabled" href="javascript:void(0)" rel="external nofollow" rel="external nofollow" >确认</a>'}
  31.       </div>
  32.     </div>`;
  33.     //设置样式,因为样式只设置一次就好,不需要实例化,所以使用静态方法
  34.     Main.setStyles();
  35.     //获取元素
  36.     Utils.getIdElem(div,this);
  37.     //监听div的点击事件
  38.     div.addEventListener("click",(e)=>this.guestsNumClickHandler(e));
  39.     //如果state为true,下拉框监听点击事件
  40.     if(this.state) this.dropDownContainer.addEventListener("click",e=>this.dropDownContainerClick(e));
  41.     //document监听点击事件,隐藏下拉框
  42.     document.addEventListener("click",e=>this.documentClick(e));
  43.     return div;
  44.   }
  45.   appendTo(parent){
  46.     Utils.appendTo(this.elem,parent);
  47.   }
  48.   guestsNumClickHandler(e){
  49.     //如果下拉框是显示状态,则直接跳出,避免重复操作
  50.     if(!Utils.hasClass(this.dropDownContainer,"none")) return;
  51.     //如果点击的不是guestsNum,直接跳出,避免事件冒泡
  52.     if(e.target.nodeName!=="SPAN"&&e.target.nodeName!=="I"&&!Utils.hasClass(e.target,"guestsNum")) return;
  53.     //给div添加聚集样式
  54.     Utils.addClass(this.elem,"focus");
  55.     //将dropDownContainer显示
  56.     Utils.removeClass(this.dropDownContainer,"none");
  57.   }
  58.   dropDownContainerClick(e){
  59.     if(e.target.nodeName==="LI"){
  60.       //点击ul选择列表
  61.       this.dropDownListClick(e);
  62.     }
  63.     else if(e.target.id==="dropDownBtn"){
  64.       //点击确认按钮
  65.       this.dropDownBtnClick();
  66.     }
  67.     else if(e.target.nodeName==="SPAN" || e.target.nodeName==="I") {
  68.       //点击span或者i标签时,将它们的父元素div作为参数
  69.       this.dropDownSelectClick(e.target.parentElement);
  70.     }
  71.     else if(Utils.hasClass(e.target,"dropDownCont")){
  72.       //点击div选择框时,将div作为参数
  73.       this.dropDownSelectClick(e.target);
  74.     }
  75.     else {
  76.       //点击下拉框内其它位置时,让当前的ul列表隐藏
  77.       if(this.listPrep) this.listPrep.style.display="none";
  78.     }
  79.   }
  80.   dropDownSelectClick(div){
  81.     //隐藏掉上一个显示的ul列表
  82.     if(this.listPrep) this.listPrep.style.display="none";
  83.     //当前点击的ul列表赋值给this.listPrep
  84.     this.listPrep=div.nextElementSibling;
  85.     //将当前点击的ul列表显示
  86.     this.listPrep.style.display="block";
  87.   }
  88.   dropDownListClick(e){
  89.     //获取当前点击的ul的tag属性值
  90.     let tag=this.listPrep.getAttribute("tag");
  91.     let unit="";
  92.     switch (tag){
  93.       case "adult": unit="成人";break;
  94.       case "children":
  95.         unit="儿童";
  96.         let txt=Number(e.target.innerText);
  97.         //根据li的数值,自动创建下面的年龄选择框
  98.         this.setDropDownItemAge(txt);
  99.         break;
  100.       case "age": unit="岁";break;
  101.     }
  102.     //将选择的li的值,显示出来
  103.     this.listPrep.previousElementSibling.firstElementChild.textContent=e.target.innerText+" "+unit;
  104.     //显示完成后,将当前显示的ul隐藏
  105.     this.listPrep.style.display="none";
  106.   }
  107.   setDropDownItemAge(txt){
  108.     let str="<span>儿童年龄</span>";
  109.     if(txt===0){
  110.       //如果是0,则年龄选择框不显示
  111.       this.ItemAge.style.display="none";
  112.     }else{
  113.       this.ItemAge.style.display="block";
  114.       //循环选择的数值,创建年龄选择框
  115.       for(let i=0;i<txt;i++){
  116.         str+=`<div class="dropDownSelect">
  117.         <div class="dropDownCont"><span><1岁</span><i></i></div>
  118.         <ul class="dropDownList" tag="age"><li><1</li>${this.setDropDownList("age")}</ul>
  119.       </div>`;
  120.       }
  121.       this.ItemAge.innerHTML=str;
  122.     }
  123.   }
  124.   dropDownBtnClick(){
  125.     //将选择的内容显示在最上方的select框内
  126.     let resultStr=this.adultNum.innerText.replace(/\s/g,"")+" "+this.childrenNum.innerText.replace(/\s/g,"");
  127.     this.elem.firstElementChild.textContent=resultStr;
  128.     //隐藏dropDownContainer
  129.     this.dropDownContainerHide();
  130.   }
  131.   documentClick(e){
  132.     //避免事件冒泡
  133.     if(e.target!==document.documentElement && e.target!==document.body) return;
  134.     //隐藏dropDownContainer
  135.     this.dropDownContainerHide();
  136.   }
  137.   dropDownContainerHide(){
  138.     //div去掉聚集状态
  139.     Utils.removeClass(this.elem,"focus");
  140.     //dropDownContainer隐藏
  141.     Utils.addClass(this.dropDownContainer,"none");
  142.     //隐藏当前显示的ul列表
  143.     if(this.listPrep) this.listPrep.style.display="none";
  144.   }
  145.   setDropDownList(type){
  146.     //创建ul下拉列表内容
  147.     let li="";
  148.     let max=0;
  149.     switch (type){
  150.       case "adult": max=8;break;
  151.       case "children": max=5;break;
  152.       case "age": max=18;break;
  153.     }
  154.     for(let i=1;i<max;i++){
  155.       li+="<li>"+i+"</li>";
  156.     }
  157.     return li;
  158.   }
  159.   static setStyles(){
  160.     if(Main.styles) return;
  161.     Main.style=true;
  162.     Utils.insertCss(".guestsNum",{
  163.       width:"108px",
  164.       height:"34px",
  165.       padding:"0px 12px",
  166.       border:"1px solid #ccc",
  167.       borderRadius:"3px",
  168.       position:"relative",
  169.       fontSize:"14px",
  170.       color:"#666",
  171.       userSelect:"none",
  172.     })
  173.     Utils.insertCss(".guestsNum.focus",{
  174.       borderColor:"#ffa800",
  175.       boxShadow:"0 0 4px #ffa800"
  176.     })
  177.     Utils.insertCss(".guestsNum>span",{
  178.       lineHeight:"34px"
  179.     })
  180.     Utils.insertCss(".guestsNum>i",{
  181.       display:"inline-block",
  182.       width:"16px",
  183.       height:"16px",
  184.       backgroundImage:"url(./image/user.jpg)",
  185.       float:"right",
  186.       margin:"8px 0px 0px 10px"
  187.     })
  188.     Utils.insertCss(".dropDownContainer",{
  189.       border: "1px solid #ffa800",
  190.       borderRadius: "4px",
  191.       boxShadow: "0 0 4px #ffa800",
  192.       backgroundColor: "#fff",
  193.       padding: "20px 15px",
  194.       width: "480px",
  195.       fontSize:"12px",
  196.       position:"absolute",
  197.       left:"0px",
  198.       top:"35px",
  199.     })
  200.     Utils.insertCss(".dropDownItem",{
  201.       marginBottom:"12px"
  202.     })
  203.     Utils.insertCss(".dropDownItem>span",{
  204.       display:"block",
  205.       width:"60px",
  206.       lineHeight:"28px",
  207.       float:"left",
  208.     })
  209.     Utils.insertCss(".dropDownSelect",{
  210.       width:"90px",
  211.       height:"30px",
  212.       marginRight:"10px",
  213.       float:"left",
  214.       position:"relative"
  215.     })
  216.     Utils.insertCss(".dropDownCont",{
  217.       border:"1px solid #ccc",
  218.       borderRadius:"3px",
  219.       height:"12px",
  220.       padding:"6px 8px 10px",
  221.     })
  222.     Utils.insertCss(".dropDownCont>span",{
  223.       display:"inline-block",
  224.       width:"53px",
  225.       height:"14px",
  226.       lineHeight:"14px",
  227.       borderRight:"1px solid #ccc"
  228.     })
  229.     Utils.insertCss(".dropDownCont>i",{
  230.       display:"inline-block",
  231.       width:"0px",
  232.       height:"0px",
  233.       border:"5px solid #c6c6c6",
  234.       borderColor:"#c6c6c6 transparent transparent",
  235.       margin: "6px 0px 0px 4px",
  236.       float: "right"
  237.     })
  238.     Utils.insertCss(".dropDownList",{
  239.       listStyle:"none",
  240.       padding:"0px",
  241.       margin:"0px",
  242.       width:"88px",
  243.       maxHeight:"200px",
  244.       overflow:"auto",
  245.       cursor:"pointer",
  246.       border:"1px solid #ccc",
  247.       backgroundColor:"#fff",
  248.       borderRadius:"4px",
  249.       position:"absolute",
  250.       left:"0px",
  251.       top:"30px",
  252.       zIndex:"2",
  253.       boxShadow: "1px 1px 3px rgba(0,0,0,.1)",
  254.       display:"none"
  255.     })
  256.     Utils.insertCss(".dropDownList>li",{
  257.       lineHeight:"28px",
  258.       paddingLeft:"8px",
  259.     })
  260.     Utils.insertCss(".dropDownList>li:hover",{
  261.       background:"#f4f4f4"
  262.     })
  263.     Utils.insertCss(".dropDownBottom",{
  264.       borderTop:"1px solid #ccc",
  265.       marginTop:"20px",
  266.       paddingTop:"20px"
  267.     })
  268.     Utils.insertCss(".dropDownTips",{
  269.       fontStyle:"normal",
  270.       fontSize: "12px",
  271.       color: "#ef523d",
  272.       lineHeight:"28px"
  273.     })
  274.     Utils.insertCss(".dropDownBtn",{
  275.       textDecoration:"none",
  276.       float: "right",
  277.       display: "inline-block",
  278.       padding: "2px 22px",
  279.       backgroundColor: "#ffb200",
  280.       borderRadius: "4px",
  281.       fontSize: "14px",
  282.       lineHeight: "24px",
  283.       color: "#fff",
  284.     })
  285.     Utils.insertCss(".dropDownBtn.disabled",{
  286.       backgroundColor: "#efefef",
  287.       color: "#999"
  288.     })
  289.     Utils.insertCss(".clearfix:after",{
  290.       content:""."",
  291.       display:"block",
  292.       overflow:"hidden",
  293.       visibility:"hidden",
  294.       clear:"both",
  295.       height:"0px"
  296.     })
  297.     Utils.insertCss(".none",{
  298.       display:"none"
  299.     })
  300.   }
  301. }
复制代码
Utils.js文件:
  1. export default class Utils{
  2.   static createE(elem,style,prep){
  3.     elem=document.createElement(elem);
  4.     if(style) for(let prop in style) elem.style[prop]=style[prop];
  5.     if(prep) for(let prop in prep) elem[prop]=prep[prop];
  6.     return elem;
  7.   }
  8.   static appendTo(elem,parent){
  9.     if (parent.constructor === String) parent = document.querySelector(parent);
  10.     parent.appendChild(elem);
  11.   }
  12.   static randomNum(min,max){
  13.     return Math.floor(Math.random*(max-min)+min);
  14.   }
  15.   static randomColor(alpha){
  16.     alpha=alpha||Math.random().toFixed(1);
  17.     if(isNaN(alpha)) alpha=1;
  18.     if(alpha>1) alpha=1;
  19.     if(alpha<0) alpha=0;
  20.     let col="rgba(";
  21.     for(let i=0;i<3;i++){
  22.       col+=Utils.randomNum(0,256)+",";
  23.     }
  24.     col+=alpha+")";
  25.     return col;
  26.   }
  27.   static insertCss(select,styles){
  28.     if(document.styleSheets.length===0){
  29.       let styleS=Utils.createE("style");
  30.       Utils.appendTo(styleS,document.head);
  31.     }
  32.     let styleSheet=document.styleSheets[document.styleSheets.length-1];
  33.     let str=select+"{";
  34.     for(var prop in styles){
  35.       str+=prop.replace(/[A-Z]/g,function(item){
  36.         return "-"+item.toLocaleLowerCase();
  37.       })+":"+styles[prop]+";";
  38.     }
  39.     str+="}"
  40.     styleSheet.insertRule(str,styleSheet.cssRules.length);
  41.   }
  42.   static getIdElem(elem,obj){
  43.     if(elem.id) obj[elem.id]=elem;
  44.     if(elem.children.length===0) return obj;
  45.     for(let i=0;i<elem.children.length;i++){
  46.       Utils.getIdElem(elem.children[i],obj);
  47.     }
  48.   }
  49.   static addClass(elem,className){
  50.     let arr=(elem.className+" "+className).match(/\S+/g);
  51.     arr=arr.filter((item,index)=>arr.indexOf(item,index+1)<0)
  52.     elem.className=arr.join(" ");
  53.   }
  54.   static removeClass(elem,className){
  55.     if(!elem.className) return;
  56.     let arr=elem.className.match(/\S+/g);
  57.     let arr1=className.match(/\S+/g);
  58.     arr1.forEach(item=>{
  59.       arr=arr.filter(t=>t!==item)
  60.     })
  61.     elem.className=arr.join(" ");
  62.   }
  63.   static hasClass(elem,className){
  64.     if(!elem.className) return false;
  65.     let arr=elem.className.match(/\S+/g);
  66.     let arr1=className.match(/\S+/g);
  67.     let res;
  68.     arr1.forEach(item=>{
  69.       res= arr.some(it=>it===item)
  70.     })
  71.     return res;
  72.   }
  73. }
复制代码
以上就是本文的全部内容,希望对各人的学习有所资助,也希望各人多多支持草根技术分享。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作