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

本文实例为大家分享了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结构代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>select</title>
</head>
<body>
  <script type="module">
    import Main from './js/Main.js';
    //参数为false时,选择框不可点击;为true时,选择框可使用
    let main=new Main(true);
    main.appendTo("body");
  </script>
</body>
</html>

Main.js文件:

import Utils from './Utils.js';
export default class Main{
  static styles=false;
  listPrep;
  constructor(state){
    //state控制下拉框是否可点击
    this.state=state;
    this.elem=this.createE();
  }
  createE(){
    if(this.elem) return this.elem;
    let div=Utils.createE("div");
    div.className="guestsNum";
    div.innerHTML=`<span>人数未定</span><i></i>
    <div class="dropDownContainer none" id="dropDownContainer">
      <div class="dropDownItem clearfix">
        <span>每间</span>
        <div class="dropDownSelect">
          <div class="dropDownCont"><span id="adultNum">2 成人</span><i></i></div>
          <ul class="dropDownList" tag="adult">${this.setDropDownList("adult")}</ul>
        </div>
        <div class="dropDownSelect">
          <div class="dropDownCont"><span id="childrenNum">0 儿童</span><i></i></div>
          <ul class="dropDownList" tag="children"><li>0</li>${this.setDropDownList("children")}</ul>
        </div>
      </div>
      <div class="dropDownItem clearfix none" id="ItemAge"></div>
      <div class="dropDownBottom clearfix">
        ${this.state?'':'<em class="dropDownTips">请优先选择日期,以便查询实时价格。</em>'}
        ${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>'}
      </div>
    </div>`;
    //设置样式,因为样式只设置一次就好,不需要实例化,所以使用静态方法
    Main.setStyles();
    //获取元素
    Utils.getIdElem(div,this);
    //监听div的点击事件
    div.addEventListener("click",(e)=>this.guestsNumClickHandler(e));
    //如果state为true,下拉框监听点击事件
    if(this.state) this.dropDownContainer.addEventListener("click",e=>this.dropDownContainerClick(e));
    //document监听点击事件,隐藏下拉框
    document.addEventListener("click",e=>this.documentClick(e));
    return div;
  }
  appendTo(parent){
    Utils.appendTo(this.elem,parent);
  }
  guestsNumClickHandler(e){
    //如果下拉框是显示状态,则直接跳出,避免重复操作
    if(!Utils.hasClass(this.dropDownContainer,"none")) return;
    //如果点击的不是guestsNum,直接跳出,避免事件冒泡
    if(e.target.nodeName!=="SPAN"&&e.target.nodeName!=="I"&&!Utils.hasClass(e.target,"guestsNum")) return;
    //给div添加聚集样式
    Utils.addClass(this.elem,"focus");
    //将dropDownContainer显示
    Utils.removeClass(this.dropDownContainer,"none");
  }
  dropDownContainerClick(e){
    if(e.target.nodeName==="LI"){
      //点击ul选择列表
      this.dropDownListClick(e);
    }
    else if(e.target.id==="dropDownBtn"){
      //点击确认按钮
      this.dropDownBtnClick();
    }
    else if(e.target.nodeName==="SPAN" || e.target.nodeName==="I") {
      //点击span或者i标签时,将它们的父元素div作为参数
      this.dropDownSelectClick(e.target.parentElement);
    }
    else if(Utils.hasClass(e.target,"dropDownCont")){
      //点击div选择框时,将div作为参数
      this.dropDownSelectClick(e.target);
    }
    else {
      //点击下拉框内其它位置时,让当前的ul列表隐藏
      if(this.listPrep) this.listPrep.style.display="none";
    }
  }
  dropDownSelectClick(div){
    //隐藏掉上一个显示的ul列表
    if(this.listPrep) this.listPrep.style.display="none";
    //当前点击的ul列表赋值给this.listPrep
    this.listPrep=div.nextElementSibling;
    //将当前点击的ul列表显示
    this.listPrep.style.display="block";
  }
  dropDownListClick(e){
    //获取当前点击的ul的tag属性值
    let tag=this.listPrep.getAttribute("tag");
    let unit="";
    switch (tag){
      case "adult": unit="成人";break;
      case "children":
        unit="儿童";
        let txt=Number(e.target.innerText);
        //根据li的数值,自动创建下面的年龄选择框
        this.setDropDownItemAge(txt);
        break;
      case "age": unit="岁";break;
    }
    //将选择的li的值,显示出来
    this.listPrep.previousElementSibling.firstElementChild.textContent=e.target.innerText+" "+unit;
    //显示完成后,将当前显示的ul隐藏
    this.listPrep.style.display="none";
  }
  setDropDownItemAge(txt){
    let str="<span>儿童年龄</span>";
    if(txt===0){
      //如果是0,则年龄选择框不显示
      this.ItemAge.style.display="none";
    }else{
      this.ItemAge.style.display="block";
      //循环选择的数值,创建年龄选择框
      for(let i=0;i<txt;i++){
        str+=`<div class="dropDownSelect">
        <div class="dropDownCont"><span><1岁</span><i></i></div>
        <ul class="dropDownList" tag="age"><li><1</li>${this.setDropDownList("age")}</ul>
      </div>`;
      }
      this.ItemAge.innerHTML=str;
    }
  }
  dropDownBtnClick(){
    //将选择的内容显示在最上方的select框内
    let resultStr=this.adultNum.innerText.replace(/\s/g,"")+" "+this.childrenNum.innerText.replace(/\s/g,"");
    this.elem.firstElementChild.textContent=resultStr;
    //隐藏dropDownContainer
    this.dropDownContainerHide();
  }
  documentClick(e){
    //避免事件冒泡
    if(e.target!==document.documentElement && e.target!==document.body) return;
    //隐藏dropDownContainer
    this.dropDownContainerHide();
  }
  dropDownContainerHide(){
    //div去掉聚集状态
    Utils.removeClass(this.elem,"focus");
    //dropDownContainer隐藏
    Utils.addClass(this.dropDownContainer,"none");
    //隐藏当前显示的ul列表
    if(this.listPrep) this.listPrep.style.display="none";
  }
  setDropDownList(type){
    //创建ul下拉列表内容
    let li="";
    let max=0;
    switch (type){
      case "adult": max=8;break;
      case "children": max=5;break;
      case "age": max=18;break;
    }
    for(let i=1;i<max;i++){
      li+="<li>"+i+"</li>";
    }
    return li;
  }
  static setStyles(){
    if(Main.styles) return;
    Main.style=true;
    Utils.insertCss(".guestsNum",{
      width:"108px",
      height:"34px",
      padding:"0px 12px",
      border:"1px solid #ccc",
      borderRadius:"3px",
      position:"relative",
      fontSize:"14px",
      color:"#666",
      userSelect:"none",
    })
    Utils.insertCss(".guestsNum.focus",{
      borderColor:"#ffa800",
      boxShadow:"0 0 4px #ffa800"
    })
    Utils.insertCss(".guestsNum>span",{
      lineHeight:"34px"
    })
    Utils.insertCss(".guestsNum>i",{
      display:"inline-block",
      width:"16px",
      height:"16px",
      backgroundImage:"url(./image/user.jpg)",
      float:"right",
      margin:"8px 0px 0px 10px"
    })
    Utils.insertCss(".dropDownContainer",{
      border: "1px solid #ffa800",
      borderRadius: "4px",
      boxShadow: "0 0 4px #ffa800",
      backgroundColor: "#fff",
      padding: "20px 15px",
      width: "480px",
      fontSize:"12px",
      position:"absolute",
      left:"0px",
      top:"35px",
    })
    Utils.insertCss(".dropDownItem",{
      marginBottom:"12px"
    })
    Utils.insertCss(".dropDownItem>span",{
      display:"block",
      width:"60px",
      lineHeight:"28px",
      float:"left",
    })
    Utils.insertCss(".dropDownSelect",{
      width:"90px",
      height:"30px",
      marginRight:"10px",
      float:"left",
      position:"relative"
    })
    Utils.insertCss(".dropDownCont",{
      border:"1px solid #ccc",
      borderRadius:"3px",
      height:"12px",
      padding:"6px 8px 10px",
    })
    Utils.insertCss(".dropDownCont>span",{
      display:"inline-block",
      width:"53px",
      height:"14px",
      lineHeight:"14px",
      borderRight:"1px solid #ccc"
    })
    Utils.insertCss(".dropDownCont>i",{
      display:"inline-block",
      width:"0px",
      height:"0px",
      border:"5px solid #c6c6c6",
      borderColor:"#c6c6c6 transparent transparent",
      margin: "6px 0px 0px 4px",
      float: "right"
    })
    Utils.insertCss(".dropDownList",{
      listStyle:"none",
      padding:"0px",
      margin:"0px",
      width:"88px",
      maxHeight:"200px",
      overflow:"auto",
      cursor:"pointer",
      border:"1px solid #ccc",
      backgroundColor:"#fff",
      borderRadius:"4px",
      position:"absolute",
      left:"0px",
      top:"30px",
      zIndex:"2",
      boxShadow: "1px 1px 3px rgba(0,0,0,.1)",
      display:"none"
    })
    Utils.insertCss(".dropDownList>li",{
      lineHeight:"28px",
      paddingLeft:"8px",
    })
    Utils.insertCss(".dropDownList>li:hover",{
      background:"#f4f4f4"
    })
    Utils.insertCss(".dropDownBottom",{
      borderTop:"1px solid #ccc",
      marginTop:"20px",
      paddingTop:"20px"
    })
    Utils.insertCss(".dropDownTips",{
      fontStyle:"normal",
      fontSize: "12px",
      color: "#ef523d",
      lineHeight:"28px"
    })
    Utils.insertCss(".dropDownBtn",{
      textDecoration:"none",
      float: "right",
      display: "inline-block",
      padding: "2px 22px",
      backgroundColor: "#ffb200",
      borderRadius: "4px",
      fontSize: "14px",
      lineHeight: "24px",
      color: "#fff",
    })
    Utils.insertCss(".dropDownBtn.disabled",{
      backgroundColor: "#efefef",
      color: "#999"
    })
    Utils.insertCss(".clearfix:after",{
      content:"\".\"",
      display:"block",
      overflow:"hidden",
      visibility:"hidden",
      clear:"both",
      height:"0px"
    })
    Utils.insertCss(".none",{
      display:"none"
    })
  }
}

Utils.js文件:

export default class Utils{
  static createE(elem,style,prep){
    elem=document.createElement(elem);
    if(style) for(let prop in style) elem.style[prop]=style[prop];
    if(prep) for(let prop in prep) elem[prop]=prep[prop];
    return elem;
  }
  static appendTo(elem,parent){
    if (parent.constructor === String) parent = document.querySelector(parent);
    parent.appendChild(elem);
  }
  static randomNum(min,max){
    return Math.floor(Math.random*(max-min)+min);
  }
  static randomColor(alpha){
    alpha=alpha||Math.random().toFixed(1);
    if(isNaN(alpha)) alpha=1;
    if(alpha>1) alpha=1;
    if(alpha<0) alpha=0;
    let col="rgba(";
    for(let i=0;i<3;i++){
      col+=Utils.randomNum(0,256)+",";
    }
    col+=alpha+")";
    return col;
  }
  static insertCss(select,styles){
    if(document.styleSheets.length===0){
      let styleS=Utils.createE("style");
      Utils.appendTo(styleS,document.head);
    }
    let styleSheet=document.styleSheets[document.styleSheets.length-1];
    let str=select+"{";
    for(var prop in styles){
      str+=prop.replace(/[A-Z]/g,function(item){
        return "-"+item.toLocaleLowerCase();
      })+":"+styles[prop]+";";
    }
    str+="}"
    styleSheet.insertRule(str,styleSheet.cssRules.length);
  }
  static getIdElem(elem,obj){
    if(elem.id) obj[elem.id]=elem;
    if(elem.children.length===0) return obj;
    for(let i=0;i<elem.children.length;i++){
      Utils.getIdElem(elem.children[i],obj);
    }
  }
  static addClass(elem,className){
    let arr=(elem.className+" "+className).match(/\S+/g);
    arr=arr.filter((item,index)=>arr.indexOf(item,index+1)<0)
    elem.className=arr.join(" ");
  }
  static removeClass(elem,className){
    if(!elem.className) return;
    let arr=elem.className.match(/\S+/g);
    let arr1=className.match(/\S+/g);
    arr1.forEach(item=>{
      arr=arr.filter(t=>t!==item)
    })
    elem.className=arr.join(" ");
  }
  static hasClass(elem,className){
    if(!elem.className) return false;
    let arr=elem.className.match(/\S+/g);
    let arr1=className.match(/\S+/g);
    let res;
    arr1.forEach(item=>{
      res= arr.some(it=>it===item)
    })
    return res;
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • javascript实现日期三级联动下拉框选择菜单

    由于工作中涉及到生日编辑资料编辑,年月日用上面网址案例:bug提示: 编辑生日栏的[年]或者[月],之前保存的具体的[日]就不显示啦,产品说不管编辑哪个数据,其他数据不变: 然后自己改了一下代码: <html> <head> <meta charset="UTF-8"/> <meta name="viewport" content="width=device-width,initial-scale=1,minimu

  • js实现可输入可选择的select下拉框

    本文实例为大家分享了可输入可选择的select下拉框,供大家参考,具体内容如下 1.原理: 1.1将input输入框和select框合并在一起,但是显示出向下点击的按钮: 这种比较容易做到 1.2出现输入值能够自动匹配的功能 动态的加载一个临时的div出现在该input下方,当点击页面中的空白地方,div隐藏. 1.3代码: <!doctype html> <html lang="en"> <head> <meta charset="

  • JavaScript实现单击下拉框选择直接跳转页面的方法

    本文实例讲述了JavaScript实现单击下拉框选择直接跳转页面的方法.分享给大家供大家参考.具体实现方法如下: <script type="text/JavaScript"> <!-- function MM_jumpMenu(targ,selObj,restore){ //v3.0 eval(targ+".location='"+selObj.options[selObj.selectedIndex].value+"'");

  • js实现下拉框选择要显示图片的方法

    本文实例讲述了js实现下拉框选择要显示图片的方法.分享给大家供大家参考.具体实现方法如下: <html> <title>下拉框选择要显示的图片</title> <body> <img width=320 height=240 src="images/m01.jpg" name="x1"> <SELECT onChange="document.x1.src=options[selectedIn

  • vuejs实现下拉框菜单选择

    本文实例为大家分享了vuejs实现下拉框菜单选择的具体代码,供大家参考,具体内容如下 方法一: <script type="text/ecmascript-6"> export default { data() { return { isShowSelect: false, dataList: [ {key: -1, value: "请选择"}, {key: 0, value: "苹果"}, {key: 1, value: "

  • js实现select下拉框选择

    最近在做一个项目需要兼容到ie不同版本,在使用select时遇到了各种问题.后来索性就自己使用原生js实现了这样一个下拉框,话不多说,直接上代码吧. <html lang="en"> <head> <meta charset="UTF-8"> <title>自定义select</title> </head> <style> *{ margin: 0; padding: 0; } #m

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

    本文实例为大家分享了js实现下拉框选择组件的具体代码,供大家参考,具体内容如下 功能需求: 1.点击div后,div显示聚焦状态,同时显示下拉框内容: 2.选择儿童人数后,如果儿童人数大于0,在下方出现对应的儿童年龄选择框数量: 3.成人人数的选择范围是1-7,儿童人数的选择范围是0-4,儿童年龄的选择范围是<1.1-17: 4.点击确认按钮后,将选择好的成人人数和儿童人数显示在最上方的div内: 5.可以控制选择框是否可点击: 6.当显示一个ul列表时,点击另一个ul列表,将上一个ul列表隐藏

  • 原生js实现下拉框功能(支持键盘事件)

    话不多说,请看代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>倒计时-多种格式调用-原生js封装</title> <link rel="shortcut icon" href="../public/image/favicon.ico" type=&qu

  • 微信小程序picker组件下拉框选择input输入框的实例

    微信小程序picker组件下拉框选择input输入框的实例 实现效果图: 页面 <view class="row-wrap"> <view class="label">预约项目</view> <picker bindchange="bindCasPickerChange" value="{{casIndex1}}" range="{{casArray}}">

  • JS获取下拉框显示值和判断单选按钮的方法

    本文实例讲述了JS获取下拉框显示值和判断单选按钮的方法.分享给大家供大家参考.具体如下: 1.本人做过很多项目,都需要得到select组件显示的值.下面是我经常用到的方法: Html源码如下: <html><body> <select id="province" name="province" > <option value="1">北京</option> <option valu

  • BootStrap中关于Select下拉框选择触发事件及扩展

    Select下拉框的问题,想在选择一个选项后,前台显示做出变动,并且知道选择的是第几个选项. 这个很好解决: 如下: <div class="page-header"> <div class="form-horizontal"> <div class="control-label col-lg-0"> </div> <div class="col-lg-2"> <

  • JS实现下拉框的动态添加(附效果)

    效果展示: 页面初加载时:      选择车类型后:      选择车颜色后:     JS实现下拉框的动态添加,网页代码如下: 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www

  • jQuery实现下拉框选择图片功能实例

    本文实例讲述了jQuery实现下拉框选择图片功能.分享给大家供大家参考.具体如下: 让下拉框中显示图片,并可选择对应图片,让select下拉框不仅可显示文字,还可以显示图片内容.为了更生动些,这里还加入了jQuery动画效果,当展开Select列表的时候,图片渐变显示.使用了一个jQ插件:imageselect.js,使用效果的朋友可以自己下载吧. 运行效果截图如下: 具体代码如下: <!DOCTYPE html> <head> <title>支持图片选择的jQuery

  • jQuery模拟下拉框选择对应菜单的内容

    先给大家展示下效果图: 下面一段代码给大家分享基于jquery实现的模拟下拉框选择对应菜单的内容,具体代码如下所示: <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style type="text/css"> body,ul,li,a,p{margin

  • js实现下拉框二级联动

    在做项目的时候,一个添加问题题目,选项和答案的问题,题目类型分为选择题,判断题,和多选题三种,此处需要添加一个二级联动的功能,即当题型为选择题的时候,正确选项的下拉框里出现的是A,B,C,D.如果题型是判断题,正确选项的下拉框内容为正确,错误,如果题型类型为多选题,则正确答案的输入框变为可输入答案型的文本框.实现效果在文末. HTML的页面如下: <div class='form-group'> <label class='col-md-2 control-label'>题型<

随机推荐