原生JS实现自定义下拉单选选择框功能

浏览器自带的原生下拉框不太美观,而且各个浏览器表现也不一致,UI一般给的下拉框也是和原生的下拉框差别比较大的,这就需要自己写一个基本功能的下拉菜单/下拉选择框了。最近,把项目中用到的下拉框组件重新封装了一下,以构造函数的方式进行封装,主要方法和事件定义在原型上,下面是主要的实现代码并添加了比较详细的注释,分享出来供大家参考。代码用了ES6部分写法如需兼容低版本浏览器请把相关代码转成es5写法,或者直接bable转下。

先放个预览图吧,后面有最终的动态效果图:(样式和交互参考了阿里和Iview UI库)

下面是主要的HTML代码(包含部分js调用代码):

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<meta http-equiv="X-UA-Compatible" content="ie=edge">

<title>Diy Select</title>

<link rel="stylesheet" href="index.css" rel="external nofollow" >

</head>

<body>

<div id="main" class="main"></div>

<script src="index.js"></script>

<script>

document.addEventListener("DOMContentLoaded",function(){

const select1 = new $Selector({

eleSelector:"#main",

options:[

{name:"选项1",value:"0"},

{name:"选项2",value:"1"},

{name:"选项3",value:"2"}

],

defaultText:"选项2"

});

})

</script>

</body>

</html>

页面中定义了id为main的div,即为选择框所要添加到的元素。传入参数即可。

接着就是样式CSS部分了,没啥说的了,手动滑稽:

* {

padding: 0;

margin: 0;

box-sizing: border-box;

}

.main {

padding: 40px;

}

.my-select {

display: inline-block;

width: auto;

min-width: 80px;

box-sizing: border-box;

vertical-align: middle;

color: #515a6e;

font-size: 14px;

line-height: normal;

position: relative;

}

.select-selection {

display: block;

box-sizing: border-box;

outline: 0;

-webkit-user-select: none;

-moz-user-select: none;

-ms-user-select: none;

user-select: none;

cursor: pointer;

position: relative;

background-color: #fff;

border-radius: 4px;

border: 1px solid #dcdee2;

transition: all .2s ease-in-out;

}

.select-selection:hover,

.select-selection.select-focus {

border-color: #57a3f3;

box-shadow: 0 0 0 2px rgba(45, 140, 240, .2);

}

.select-selected-value {

display: block;

height: 28px;

line-height: 28px;

font-size: 12px;

overflow: hidden;

text-overflow: ellipsis;

white-space: nowrap;

padding-left: 8px;

padding-right: 24px;

}

.icon-select-arrow {

position: absolute;

top: 50%;

right: 8px;

line-height: 1;

margin-top: -7px;

font-size: 14px;

color: #808695;

transition: all .2s ease-in-out;

display: inline-block;

font-style: normal;

font-weight: 400;

font-variant: normal;

text-transform: none;

text-rendering: auto;

line-height: 1;

-webkit-font-smoothing: antialiased;

-moz-osx-font-smoothing: grayscale;

vertical-align: middle;

}

.icon-select-arrow::before {

content: "";

display: block;

width: 6px;

height: 6px;

background-color: transparent;

border-left: 1.5px solid #808695;

border-bottom: 1.5px solid #808695;

transform: rotate(-45deg);

}

.select-dropdown {

width: auto;

min-width: 80px;

max-height: 200px;

overflow: auto;

margin: 5px 0;

padding: 5px 0;

background-color: #fff;

box-sizing: border-box;

border-radius: 4px;

box-shadow: 0 1px 6px rgba(0, 0, 0, .2);

position: absolute;

z-index: 2;

transform-origin: center top 0px;

transition: all 0.3s;

will-change: top, left;

top: 30px;

left: 0;

transform: scale(1, 0);

opacity: 0;

}

.select-item {

line-height: normal;

padding: 7px 16px;

clear: both;

color: #515a6e;

font-size: 12px !important;

white-space: nowrap;

list-style: none;

cursor: pointer;

transition: background .2s ease-in-out;

}

.select-item.select-item-selected,

.select-item:hover {

color: #2d8cf0;

background-color: #f3f3f3;

}

样式部分就不做什么解释了,下面放入压轴的JS,同样也无需过多解释,注释写的很详细了,上代码:

/* jshint esversion: 6 */

(function (window, document) {

let Selector = function (option) {

//执行初始化方法,

this._init(option);

};

Selector.prototype = {

//初始化传入参数并定义初始化的相关变量

_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(); //初始化后执行创建元素方法

},

//创建下拉选择框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);

},

//点击下拉框事件处理函数

_selectHandleClick() {

if (this.dropboxShow) {

this._selectDropup();

} else {

this._selectDropdown();

}

},

//收起下拉选项

_selectDropup() {

this.eleDrop.style.transform = "scale(1,0)";

this.eleDrop.style.opacity = "0";

this.eleSelect.className = "select-selection";

this.dropboxShow = false;

},

//展示下拉选项

_selectDropdown() {

this.eleDrop.style.transform = "scale(1,1)";

this.eleDrop.style.opacity = "1";

this.eleSelect.className = "select-selection select-focus";

this.dropboxShow = true;

},

//点击下拉选项进行赋值

_dropItemClick(ele) {

this.defaultValue = ele.getAttribute("data-value");

//document.querySelector("#select-value").value = ele.getAttribute("data-value");

this.eleSpan.innerText = ele.innerText;

ele.className = "select-item select-item-selected";

//对点击选中的其他所有兄弟元素修改class去除选中样式

this._siblingsDo(ele, function (ele) {

if (ele) {

ele.className = "select-item";

}

});

this._selectDropup();

},

//node遍历是否是子元素包裹元素

_getTargetNode(ele, target) {

//ele是内部元素,target是你想找到的包裹元素

if (!ele || ele === document) return false;

return ele === target ? true : this._getTargetNode(ele.parentNode, target);

},

//兄弟元素遍历处理函数

_siblingsDo(ele, fn) {

(function (ele) {

fn(ele);

if (ele && ele.previousSibling) {

arguments.callee(ele.previousSibling);

}

})(ele.previousSibling);

(function (ele) {

fn(ele);

if (ele && ele.nextSibling) {

arguments.callee(ele.nextSibling);

}

})(ele.nextSibling);

},

//绑定下拉框事件处理函数

_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;

})(window, document);

到此,一个自定义下拉菜单就出炉了,下面是动态效果:

至此,从css自定义的表单元素到下拉框元素都已经自定义完毕,使用bootstrap的同学把这些加进去就能基本保持各浏览器效果一致性和美观性了,就到这吧先。

推荐:

感兴趣的朋友可以关注小编的微信公众号【码农那点事儿】,更多网页制作特效源码及学习干货哦!!!

总结

以上所述是小编给大家介绍的原生js实现一个自定义下拉单选选择框功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!

以上是 原生JS实现自定义下拉单选选择框功能 的全部内容, 来源链接: utcz.com/z/352036.html

回到顶部