原生js实现一个自定义下拉单选选择框

 浏览器自带的原生下拉框不太美观,而且各个浏览器表现也不一致,UI一般给的下拉框也是和原生的下拉框差别比较大的,这就需要自己写一个基本功能的下拉菜单/下拉选择框了。最近,把项目中用到的下拉框组件重新封装了一下,以构造函数的方式进行封装,主要方法和事件定义在原型上,下面是主要的实现代码并添加了比较详细的注释,分享出来供大家参考。代码用了ES6部分写法如需兼容低版本浏览器请把相关代码转成es5写法,或者直接bable转下。   先放个预览图吧,后面有最终的动态效果图:(样式和交互参考了阿里和Iview UI库)    下面是主要的HTML代码(包含部分js调用代码): View Code   HTML部分就放置了一个id为main的包裹div,即为下拉菜单所要添加到的元素。最底部为调用的js,传入相应的参数即可。其中eleSelector为要挂载到的dom节点所在的选择器,此处我们演示,选择挂载到id为main的div;第2个参数为所要展示的下拉元素数组对象,name为下拉选择的文本内容,value为对应的值,此处我们传入了三个选项对象,生成的下拉框中将会有三个选项;第三个参数为所要展示的默认文本,如果为空,则默认为“未选择”。 接着就是样式CSS部分: View Code 样式部分就不做什么解释了,下面放入压轴的JS,注释写的比较详细,上代码: View Code 代码分解: 复制代码 (function (window, document) { let Selector = function (option) { //执行初始化方法, this._init(option); }; })(window, document); 复制代码 这是第一部分:自执行函数,形成封闭的作用域,避免全局污染。同时传入windwo和document对象,window和document作为了作用域中的局部变量, 这样局部作用域就不需要内部函数沿着作用域链再查找到最顶层的window了,提高运行效率。之后定义自定义选择器的构造方法,并执行初始化初始化方法,初始化方法我们将在原型中进行定义,见下文。 复制代码 _init({   eleSelector = "", //传入的选择器 id,class,tag等,用于将选择框渲染到此选择器所在的元素   options = [{   name: "请选择",     value: "0",   }], //传入的下拉框对象,name为选择的文字,value为值   defaultText = "请选择" //提供的默认选择的值   }) { //将传入的数据绑定到this上   this.parentEle = document.querySelector(eleSelector) || document.body; //要邦定的dom   this.options = options; //选择值数组对象   this.defaultText = defaultText; //默认值   this.dropboxShow = false; //定义存储下拉框的显示隐藏状态   this.defaultValue = ""; //定义村赤默认选中的值   this._creatElement(); //初始化后执行创建元素方法 }, 复制代码 第二部分为初始化方法,将传入的对象进行解构赋值,并定义变量的默认值,之后将传入的变量挂载到this实例上,同时定义初始化其他变量存储需要的值。数据初始化完毕,此时就改创建生成下拉菜单的元素了,此时变调用创建元素的方法_creatElememt()。接着就是定义创建元素方法了。 复制代码     //创建下拉选择框dom _creatElement() { //选择框最外层的包裹元素 let wrapEle = document.createElement("div"); wrapEle.className = "my-select"; //根据传入的值获取选择框默认的值和内容 this.options.forEach(item => { if (item.name === "this.defaultText") { this.defaultValue = item.value; } }); let selectWarpBox = document.createElement("div"); //选择框包裹元素 selectWarpBox.className = "select-selection"; let inputHideBox = document.createElement("input"); //隐藏保存选择值得元素 inputHideBox.type = "hidden"; inputHideBox.value = this.defaultValue; let selectShowBox = document.createElement("div"); //选择框默认展示框 let selectNameBox = document.createElement("span"); //选择框展现的值ele selectNameBox.className = "select-selected-value"; selectNameBox.id = "select-option"; selectNameBox.innerText = this.defaultText; //将传入的默认值赋值 let selectIcon = document.createElement("i"); //图标ele selectIcon.className = "arrow-down icon-select-arrow"; //将span和角标添加到外层div selectShowBox.appendChild(selectNameBox); selectShowBox.appendChild(selectIcon); selectWarpBox.appendChild(inputHideBox); selectWarpBox.appendChild(selectShowBox); //下拉框 let dropbox = document.createElement("div"), ulbox = document.createElement("ul"); dropbox.id = "select-drop"; dropbox.className = "select-dropdown"; ulbox.className = "select-dropdown-list"; //遍历传入的选项数组对象,生成下拉菜单的li元素并赋值 this.options.forEach((item) => { let itemLi = document.createElement("li"); if (this.defaultText === item.name) { itemLi.className = "select-item select-item-selected"; } else { itemLi.className = "select-item"; } itemLi.setAttribute("data-value", item.value); itemLi.innerText = item.name; ulbox.appendChild(itemLi); }); //将下拉框ul推入到包裹元素 dropbox.appendChild(ulbox); wrapEle.appendChild(selectWarpBox); wrapEle.appendChild(dropbox); this.parentEle.appendChild(wrapEle); //将生成的下拉框添加到所选元素中 //把需要操作的dom挂载到当前实例 //this.wrapEle = wrapEle; //最外层包裹元素 this.eleSelect = selectWarpBox; //选择框 this.eleDrop = dropbox; //下拉框 this.eleSpan = selectNameBox; //显示文字的span节点 //绑定事件处理函数 this._bind(this.parentEle); }, 复制代码 这一部分主要是创建组成下拉框的dom元素以及对应关系,并将需要的dom节点挂载到this实例对象上,便于后续进行事件处理。最后将组装好的dom节点添加到传入的选择器对象中,即传入的第一个参数所属的dom对象。此时页面中将渲染出一个自定义的下拉选择框。下一步就是绑定事件处理函数,处理交互事件,即最后调用了_bind()方法,将定义的相关事件处理函数绑定到对应的dom。 复制代码 //绑定下拉框事件处理函数 _bind(parentEle) { let _this = this; //事件委托到最外层包裹元素进行绑定处理 parentEle.addEventListener("click", function (e) { const ele = e.target; //遍历当前点击的元素,如果是选中框内的元素执行 if (_this._getTargetNode(ele, _this.eleSelect)) { if (_this.dropboxShow) { _this._selectDropup(); } else { _this._selectDropdown(); } } else if (ele.className === "select-item") { //如果是点击的下拉框的选项执行 _this._dropItemClick(ele); } else { //点击其他地方隐藏下拉框 _this._selectDropup(); } }); }   //将构造函数挂载到全局window   window.$Selector = Selector; 复制代码 这一部分主要就是进行事件的绑定了,我们传入了一个parentELe的dom对象,此对象即为我们传入的选择器对应的元素,然后通过此对象进行事件委托处理下面的其他交互事件。最后将构造函数暴露到全局对象window,以便在全局上的调用。到此,一个自定义下拉菜单就出炉了,下面是动态效果: 至此,从css自定义的表单元素到下拉框元素都已经自定义完毕,使用bootstrap的同学把这些加进去就能基本保持各浏览器效果一致性和美观性了,就先写道这吧,后续有时间在进行优化。 海纳百川,有容乃大;壁立千仞,无欲则刚。人要有胸怀方能成大事,不要被欲望所驱使,方能风吹不动浪打不摇。 不积跬步无以至千里,不积小流无以成江海。从事技术工作,要时刻学习积累,即使不能一专多能也应术业有专攻,方能以不变应万变。https://www.cnblogs.com/websharehome/p/9772755.html
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信