欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

js自定义的可分类可搜索的下拉框组件

程序员文章站 2022-04-14 16:09:10
html5搜索框结合datalist可以实现带搜索功能的下拉框 不过尝试了下,使用optgroup分组发现没效果 search ......

html5搜索框结合datalist可以实现带搜索功能的下拉框

不过尝试了下,使用optgroup分组发现没效果

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>search</title>
</head>
<body>
    <input type="text" list="data" id="mylist">
    <datalist id="data">
        <optgroup label="基础"> 
            <option value="html">html</option>
            <option value="css">css</option>
            <option value="js">js</option>
        </optgroup>
        <optgroup label="框架"> 
            <option value="vue">vue</option>
            <option value="react">react</option>
        </optgroup>
    </datalist>
</body>
</html>

js自定义的可分类可搜索的下拉框组件

 

 

自己写一个可以搜索和已经归类的下拉框

放出效果图

js自定义的可分类可搜索的下拉框组件

 

目录结构

js自定义的可分类可搜索的下拉框组件

 

 

index.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>search</title>
    <style>
        *{
            margin:0;
            padding:0;
            box-sizing: border-box;
        }
        body{
            background:#eee;
            font-size:14px;
            font-family: "微软雅黑"
        }
        @font-face {
          font-family: "iconfont";
          src: url('font/iconfont.eot?t=1585396588464'); /* ie9 */
          src: url('font/iconfont.eot?t=1585396588464#iefix') format('embedded-opentype'), /* ie6-ie8 */
          url('data:application/x-font-woff2;charset=utf-8;base64,d09gmgabaaaaaakyaasaaaaabkaaaajmaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaheigvgcccapmzwe2aiqdcasgaaqgbyrtby8bjaxiljgfawcsqik0gifz91t6awaghv7b73/7zj1vkle0i0dipn8wrss8zupnkdxy2/81tzgey6suyyoakej/kh/auywkcjn2s2zkjuqmxovbvu6jm2qlefvylb5xprzpczm9cxqg8wod42gu2oswtepfys8okmc9miotkagmg8yueih3cvtr15pz29g7hllmxhais8fsofxiydirvwrldxuzek5mzxqafvas+n58trxlkrkc3xb4bd2e2qdornhseiigjanocbkkzakzog0s7msjxuvuf/kgwbfqgw9kpcavjuor7k+zq2tbl1sfsfp0ry0nekxb7co0se8i2u/fc/x1j21nl8xdm7a2ox0xly0t51al0ul7st9/ovl6t/vdf42boz8vq6kjg6dl4adxwmv/k2syejflyj3hekjctzd4h9ranmwybf/kmty4nlsfp6lanupwpnn/vgfbysuhutueuiw+divko2rmz1gmxirkvdpetrmbh2u0ydmrqzdtfia0ekns7y0kjx7jzp6htlsvyjvgdtxoo+xmguphvhezncet9qt0jchubkcqce0+wse+xnldxb8tp04ax4nrubxjifesg9jtaykiuheu4az4jhw/wpgjlwwz2clxddhuts8agfeavbsy0qhiqrolyggihfqwwlqrn99hlcd8gu7oqiupezzyjkdja6mb5ky1hnt1km+ktlkmhfcqwiibtafmez8vgulmws5ieap2hfxsauj0u0otg+3twd8dg2q2k4uzpvb2x9f8dqaaaa==') format('woff2'),
          url('font/iconfont.woff?t=1585396588464') format('woff'),
          url('font/iconfont.ttf?t=1585396588464') format('truetype'), /* chrome, firefox, opera, safari, android, ios 4.2+ */
          url('font/iconfont.svg?t=1585396588464#iconfont') format('svg'); /* ios 4.1- */
        }

        .iconfont {
          font-family: "iconfont" !important;
          font-size: 16px;
          font-style: normal;
          -webkit-font-smoothing: antialiased;
          -moz-osx-font-smoothing: grayscale;
        }
        .icon-xiala:before {
          content: "\e65c";
          color:#fff;
        }
        .container{
            margin:50px auto;
            width:200px;
            
        }
        .input-box{
            position: relative;
            width:202px;
            height:25px;
        }
        .input{
            width:200px;
            border:1px solid rgb(75,151,252);    
            height:25px;    
            padding:3px 8px;    
        }
        .btn{
            position: absolute;
            right:0;
            top:0;
            width:25px;
            height:25px;
            height:100%;
            background-color: rgb(75,151,252);    
            text-align:center;
            cursor: pointer;
        }
        .list-box{
            width:200px;
            height:auto;
            overflow-y:scroll;
            background-color: #fff;
            padding:5px;
            max-height:200px;
            display: none;
        }
        .search{
            width:100%;
            margin-bottom:5px;
            padding:2px;

        }
        input::-webkit-input-placeholder{
            font-size:12px;
        }
        dl{
            width:100%;
            height:auto;
            line-height:25px;
            margin-top:5px;
        }
        dd{
            padding-left:10px;
            cursor: pointer;
        }
        dt{
            font-weight:bold;
        }
        .info{
            text-align:center;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="input-box">
            <input type="text" class="input">
            <div class="btn"><i class="iconfont icon-xiala"></i></div>
        </div>
        <div class="list-box">
            <input type="text" class="search" placeholder="搜索">
            <!-- <dl>
                <dt>基础</dt>
                <dd>html</dd>
                <dd>css</dd>
                <dd>js</dd>
                <dd>jquery</dd>
            </dl>
            <dl>
                <dt>框架</dt>
                <dd>vue</dd>
                <dd>react</dd>
                <dd>angular</dd>
            </dl> -->
        </div>
    </div>
    <div class="info">
        <p>之前的值是:<span class="prev"></span></p>
        <p>改变后的值是:<span class="now"></span></p>
    </div>

    <script src="data.js"></script>
    <script src="index.js"></script>
    <script>
        window.onload=function(){
            let mysearch=new $search({
                data
            });
        }
    </script>
</body>
</html>

 

data.js  数据

//数据对象
const data={
    "基础":["html","css","js","jquery"],
    "框架":["vue","react","angular"]
}

 

index.js

(function(window,document){

    //构造函数
    function search(data){
        this.data=data.data;
        this.previnfo="空";
        this.nowinfo="空";
        this.showlistflag=false;
        
        this.todom(this.data);//生成dom
        this.bindsearch();//绑定搜索框事件
        this.clickdd();//点击dd事件
    }

    //生成dom
    search.prototype.todom=function(data){
        let templates=``;

        for(let d in data){    

            let ddtemplates="";
            for(let i=0;i<data[d].length;i++){
                ddtemplates+=`
                    <dd>${ data[d][i] }</dd>
                `;
            }

            templates+=`
                <dl>
                    <dt>${ d }</dt>
                    `+
                    ddtemplates
                    +`
                </dl>
            `;
        }

        document.queryselector(".list-box").innerhtml+=templates;
        document.queryselector(".prev").innerhtml=this.previnfo;
        document.queryselector(".now").innerhtml=this.nowinfo;

        //点击显示下拉框
        document.queryselector(".input-box").addeventlistener("click",()=>{
            if(this.showlistflag){
                this.hidelist();
            }else{
                this.showlist();
            }
            
        })
    }

    //隐藏下拉框
    search.prototype.hidelist=function(){
        document.queryselector(".list-box").style.display="none";
        document.queryselector(".search").value="";
        this.showlistflag=true;
    }

    //显示下拉框
    search.prototype.showlist=function(){
        document.queryselector(".list-box").style.display="block";
        document.queryselector(".search").value="";
        let dds=document.queryselectorall("dd");
        
        dds.foreach(function(dd,index){
            dd.style.display="block";
        })
        this.showlistflag=true;
    }

    //绑定搜索框事件
    search.prototype.bindsearch=function(){
        let search=document.queryselector(".search");

        search.addeventlistener("keyup",()=>{
            let str=search.value;    
            this.hidedd(str);//隐藏不包含搜索内容的dd
        })
    }

    //隐藏不包含搜索内容的dd
    search.prototype.hidedd=function(str){
        let dds=document.queryselectorall("dd");
        
        dds.foreach(function(dd,index){
            dd.style.display="block";

            //不包含搜索内容的dd
            if(dd.innertext.indexof(str)===-1){
                //隐藏
                dd.style.display="none";
            }
            
        })
    }

    //点击dd事件
    search.prototype.clickdd=function(){
        //事件代理
        document.queryselector(".list-box").addeventlistener("click",(e)=>{
            if(e.target.nodename!=="dd") return;

            if(this.showlistflag){
                this.hidelist();
            }else{
                this.showlist();
            }
            this.showlistflag=!this.showlistflag;
            
            //更新info
            document.queryselector(".prev").innerhtml=document.queryselector(".input").value;            

            let val=e.target.innertext;
            document.queryselector(".input").value=e.target.innertext;

            //更新info
            document.queryselector(".now").innerhtml=document.queryselector(".input").value;
        })
        
    }

    window.$search=search;
})(window,document);