一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服務器之家 - 編程語言 - JavaScript - js教程 - 原生js實現下拉框選擇組件

原生js實現下拉框選擇組件

2022-01-05 17:07蒲公英芽 js教程

這篇文章主要為大家詳細介紹了原生js實現下拉框選擇組件的開發(fā),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了js實現下拉框選擇組件的具體代碼,供大家參考,具體內容如下

功能需求:

1、點擊div后,div顯示聚焦狀態(tài),同時顯示下拉框內容;
2、選擇兒童人數后,如果兒童人數大于0,在下方出現對應的兒童年齡選擇框數量;
3、成人人數的選擇范圍是1-7,兒童人數的選擇范圍是0-4,兒童年齡的選擇范圍是<1、1-17;
4、點擊確認按鈕后,將選擇好的成人人數和兒童人數顯示在最上方的div內;
5、可以控制選擇框是否可點擊;
6、當顯示一個ul列表時,點擊另一個ul列表,將上一個ul列表隱藏;
7、點擊隱藏框內除綁定事件元素外,將正在顯示的ul列表隱藏;
8、點擊頁面中任意空白位置,將顯示的下拉框內容整體隱藏;

下拉框不可操作時的顯示狀態(tài):

原生js實現下拉框選擇組件

下拉框可操作時:

原生js實現下拉框選擇組件

選擇兒童人數后,下方自動出現對應數量的兒童年齡選擇框:

原生js實現下拉框選擇組件

點擊確認按鈕后,將結果顯示在是上方的div內:

原生js實現下拉框選擇組件

剛開始的想法是對select、ul下拉列表、btn按鈕分別進行事件監(jiān)聽,此外還要有當點擊下拉框內其它位置時,ul下拉列表隱藏、當點擊body時整個下拉框內容隱藏。監(jiān)聽事件過多,而且事件冒泡也會影響事件的執(zhí)行,導致某些事件會出現執(zhí)行多次的情況。

兒童年齡的選擇框是根據兒童的人數來生成的,有幾個兒童,就有幾個年齡選擇框。這種情況下,年齡的選擇框肯定是動態(tài)創(chuàng)建的,無法針對年齡的select進行事件監(jiān)聽,只能采用事件委托的形式,所以最后把對select、ul下拉列表、btn按鈕的點擊事件,還有當點擊container內其它位置時,ul下拉列表隱藏。全部委托給了dropDownContainer元素。

下面附上代碼

html結構代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!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文件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
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">請優(yōu)先選擇日期,以便查詢實時價格。</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>`;
    //設置樣式,因為樣式只設置一次就好,不需要實例化,所以使用靜態(tài)方法
    Main.setStyles();
    //獲取元素
    Utils.getIdElem(div,this);
    //監(jiān)聽div的點擊事件
    div.addEventListener("click",(e)=>this.guestsNumClickHandler(e));
    //如果state為true,下拉框監(jiān)聽點擊事件
    if(this.state) this.dropDownContainer.addEventListener("click",e=>this.dropDownContainerClick(e));
    //document監(jiān)聽點擊事件,隱藏下拉框
    document.addEventListener("click",e=>this.documentClick(e));
    return div;
  }
  appendTo(parent){
    Utils.appendTo(this.elem,parent);
  }
  guestsNumClickHandler(e){
    //如果下拉框是顯示狀態(tài),則直接跳出,避免重復操作
    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的數值,自動創(chuàng)建下面的年齡選擇框
        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";
      //循環(huán)選擇的數值,創(chuàng)建年齡選擇框
      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去掉聚集狀態(tài)
    Utils.removeClass(this.elem,"focus");
    //dropDownContainer隱藏
    Utils.addClass(this.dropDownContainer,"none");
    //隱藏當前顯示的ul列表
    if(this.listPrep) this.listPrep.style.display="none";
  }
  setDropDownList(type){
    //創(chuàng)建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文件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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;
  }
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/Charissa2017/article/details/104111603

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: meyd–456佐山爱在线播放 | 国产日日干 | 污漫日本E同人 | 朝鲜美女免费一级毛片 | 午夜一级毛片看看 | 亚洲精品有码在线观看 | 日日干夜夜拍 | 18韩国美女vip视频7 | 精品国产美女AV久久久久 | sese在线| 天天做天天爱天天综合网 | 色综合久久天天综合观看 | 男人天堂新 | 二次元美女扒开内裤露尿口 | 成年私人影院免费视频网站 | 毛片一级毛片 | 国产91精品区 | 男人女人日皮 | 国产一区二区三区四区波多野结衣 | 车上小婕子系列辣文小说 | www.大逼色| 精品久久久久国产免费 | 极品虎白女在线观看一线天 | 欧美亚洲另类在线观看 | 亚洲人成网站在线观看播放青青 | chinese456老年gay| 精品无码久久久久久久动漫 | 亚欧精品在线观看 | 国产精品久久久久久久久ktv | 国产精品久久久99 | 亚洲精品AV无码永久无码 | 久久久黄色片 | 国产国拍亚洲精品av | 99精品视频在线观看 | 国产啪精品视频网给免丝袜 | 国产精品免费看香蕉 | 日韩欧美国产成人 | 青青青青久久国产片免费精品 | 欧美激情亚洲 | 成人看的羞羞视频免费观看 | 男人叼女人的痛爽视频免费 |