原生 select 带搜索功能

  随着前端功能的不断完善带搜索的选择框也是迫切需要的,但是原生的搜索框不支持这个功能,所以就开发了一个

  思考:怎么将代码可以封装到很完善,很简洁,是函数的闭包加回调函数好,还是要面向对象的写法好(此案例采用第一种)

  重点:select 标签 html5 新增的 size 属性

  只要将此代码复制粘贴即可查看效果

  实现思路:select方法,向外暴露了两个方法,一个是setData 填充数据,一个是curData 查看选中数据,

       select有两个参数,一个是dom元素,一个是配置内容

       初始时,会将固定的内容拼接到dom元素下面,配置内容分为两种,一种是固定的内容,一种是回调函数的内容,我还为了省事,将dom元素下的input 元素 及 select 元素暴露出去,

       从而进行dom操作来满足大部分的业务需求,

  

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            #demo1{
                margin-top: 20px;
                margin-left: 20px;
                width: 300px;
                height: 20px;
            }
        </style>
        
    </head>
    <body>
        <button onclick="fn()"> 获取 </button>
        <div id="demo1"></div>
        
    </body>
    <script>
        // dom 元素,obj 配置 
        function select(dom, obj){
            
            function init(){
                if(!window.selectSearchInput){
                    window.selectSearchInput = 500;
                }
                window.selectSearchInput -= 2;
                var selectSearchInput = window.selectSearchInput
                if(obj.selectSearchInput){
                    selectSearchInput = obj.selectSearchInput
                }
                var style = document.createElement('style');
                style.innerHTML = '#'+dom.id +' .select-search{\
                                        position: relative;\
                                        height: 100%;\
                                    }\
                                    #'+dom.id +' .select-search .select-search-input{\
                                        width: 100%;\
                                        height: 100%;\
                                        position: absolute;\
                                        z-index: ' + selectSearchInput + '; \
                                        box-sizing: border-box;\
                                        top: 0;\
                                        left: 0;\
                                    }\
                                    #'+dom.id +' .select-search .select-search-select{\
                                        width: 100%;\
                                        position: absolute;\
                                        z-index: ' + selectSearchInput + '; \
                                        top: 0;\
                                        left: 0;\
                                        outline: none;\
                                    }\
                                    #'+dom.id +' .select-search .select-search-select option{\
                                        height: '+ dom.offsetHeight +'px;\
                                        cursor: pointer;\
                                    }\
                                    #'+dom.id +' .select-search .select-search-select option:hover{\
                                        color: #fff;\
                                        background: #5897fb;\
                                    }'
                var ref = document.querySelector('script');    
                ref.parentNode.insertBefore(style, ref);
                var str = '';
                str += '<div class="select-search">\
                            <select size="0" class="select-search-select"></select>\
                            <input type="text" class="select-search-input">\
                        </div>'
                dom.innerHTML = str;
                
            }
            init();
            // input 元素操作
            var input = dom.getElementsByClassName('select-search-input')[0];
            // select 元素操作
            var select = dom.getElementsByClassName('select-search-select')[0];
            // 数据源
            var datasoure = [];
            // 当前数据
            var currsoure = [];
            // 事件触发
            var time = null;
            
            if(obj.input){
                obj.input(input);
            }
            if(obj.select){
                obj.select(select);
            }
            
            // 填充select的数据
            function selectData(data){
                var str = '<option> 占位符 </option>';
                for(var i=0;i<data.length;i++){
                    str += '<option value='+data[i].id+' indexKey='+ data[i].indexKey +'> '+ data[i].text +' </option>';
                }
                select.innerHTML = str;
            }
            // 设置 data
            function setData(data){
                
                for(var i=0;i<data.length;i++){
                    data[i].indexKey = i;
                }
                datasoure = data;
                if(obj.isSelectHtml){
                    select.innerHTML = data;
                } else {
                    selectData(data);
                }
                
            }
            // 获取当前选中状态
            function curData(){
                return currsoure;
            }
            // 点击展开select标签
            input.onfocus = function(e){
                select.setAttribute('size', obj.size? obj.size : '7');
            }
            // input失焦关闭select标签
            input.onblur = function(e){
                setTimeout(function() {
                    select.setAttribute('size', '');
                }, 250)
            }
            // 实时获取input值
            input.oninput = function(e){
                // 延迟执行,防止一直调接口
                if(time!=null){
                    clearTimeout(time)
                }
                time=setTimeout(function(){
                    var val = e.target.value;
                    currsoure = [];
                    if(obj.isRequest){
                        obj.search(val);
                    }
                    else {
                        var patty = new RegExp(val);
                        var arr = [] 
                        for(var i=0;i<datasoure.length;i++){
                            if(patty.test(datasoure[i].text)){
                                arr.push(datasoure[i])
                            }
                        }
                        selectData(arr);
                    }
                },obj.delay? obj.delay: 500)
                
            }
            // 获取选择是值
            select.onchange = function(e){
                var option = dom.getElementsByTagName('option');
                var str = ''
                currsoure = [];
                for(var i=1;i<option.length;i++){
                    if(option[i].selected){
                        var indexKey = option[i].getAttribute('indexKey')
                        currsoure.push(datasoure[indexKey]);
                        str += datasoure[indexKey].text + ',';
                    }
                }
                input.value = str.slice(0,str.length-1);
                this.setAttribute('size', '0');
            }
            return {
                setData,    // 设置数据
                curData,    // 获取选中内容
            }
        }
        var arr = [];
        for(var i=0;i<50;i++){
            arr.push({
                id: i+'',
                text: '这是对应的值'+i
            })
        }
        
        var config = select(document.getElementById('demo1'), {
            size: '7', // 展示的数据
            selectSearchInput: 500, // 自定义z-index
            delay: 500, // 延迟时间
            isRequest: false, // 是否自定义搜索
            isSelectHtml: false, // 是否自定义option内容
            input: function(e){ // input 的dom操作
                // console.log(e)
                e.setAttribute('placeholder','请选择内容')
            },
            select: function(e){ // select 的dom操作
                // console.log(e);
            },
            search: function(e){ // 带搜索
                config.setData(arr);
            },
        })
        config.setData(arr);
        
        function fn(){
            console.log(config.curData());
        }
    </script>
</html>

 在安利一个小技巧

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <input type="text" id="input">
    </body>
    <script>
        var input = document.getElementById('input');
        function fn(dom) {
            function on(event, handler){
                dom[event] = handler
            }
            return {
                on
            };
        }
        var f = fn(input);
        f.on('oninput',function(e){
            console.log(e);
        })
    </script>
</html>

 

posted on 2021-10-16 18:06  Web引领者  阅读(3396)  评论(0编辑  收藏  举报