溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何使用原生JS實(shí)現(xiàn)自定義下拉單選選擇框功能

發(fā)布時(shí)間:2021-04-20 10:28:56 來源:億速云 閱讀:835 作者:小新 欄目:web開發(fā)

這篇文章主要介紹了如何使用原生JS實(shí)現(xiàn)自定義下拉單選選擇框功能,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

js的作用是什么

1、能夠嵌入動態(tài)文本于HTML頁面。2、對瀏覽器事件做出響應(yīng)。3、讀寫HTML元素。4、在數(shù)據(jù)被提交到服務(wù)器之前驗(yàn)證數(shù)據(jù)。5、檢測訪客的瀏覽器信息。6、控制cookies,包括創(chuàng)建和修改等。7、基于Node.js技術(shù)進(jìn)行服務(wù)器端編程。

瀏覽器自帶的原生下拉框不太美觀,而且各個(gè)瀏覽器表現(xiàn)也不一致,UI一般給的下拉框也是和原生的下拉框差別比較大的,這就需要自己寫一個(gè)基本功能的下拉菜單/下拉選擇框了。最近,把項(xiàng)目中用到的下拉框組件重新封裝了一下,以構(gòu)造函數(shù)的方式進(jìn)行封裝,主要方法和事件定義在原型上,下面是主要的實(shí)現(xiàn)代碼并添加了比較詳細(xì)的注釋,分享出來供大家參考。代碼用了ES6部分寫法如需兼容低版本瀏覽器請把相關(guān)代碼轉(zhuǎn)成es5寫法,或者直接bable轉(zhuǎn)下。

先放個(gè)預(yù)覽圖吧,后面有最終的動態(tài)效果圖:(樣式和交互參考了阿里和Iview UI庫)

如何使用原生JS實(shí)現(xiàn)自定義下拉單選選擇框功能

下面是主要的HTML代碼(包含部分js調(diào)用代碼):

<!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:"選項(xiàng)1",value:"0"},
          {name:"選項(xiàng)2",value:"1"},
          {name:"選項(xiàng)3",value:"2"}
        ],
        defaultText:"選項(xiàng)2"
      });
    })
  </script>
</body>
</html>

頁面中定義了id為main的div,即為選擇框所要添加到的元素。傳入?yún)?shù)即可。

接著就是樣式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,同樣也無需過多解釋,注釋寫的很詳細(xì)了,上代碼:

/* jshint esversion: 6 */
(function (window, document) {
  let Selector = function (option) {
    //執(zhí)行初始化方法,
    this._init(option);
  };

  Selector.prototype = {
    //初始化傳入?yún)?shù)并定義初始化的相關(guān)變量
    _init({
      eleSelector = "", //傳入的選擇器 id,class,tag等,用于將選擇框渲染到此選擇器所在的元素
      options = [{
        name: "請選擇",
        value: "0",
      }], //傳入的下拉框?qū)ο?,name為選擇的文字,value為值
      defaultText = "請選擇" //提供的默認(rèn)選擇的值
    }) {
      
      //將傳入的數(shù)據(jù)綁定到this上
      this.parentEle = document.querySelector(eleSelector) || document.body; //要邦定的dom 
      this.options = options; //選擇值數(shù)組對象
      this.defaultText = defaultText; //默認(rèn)值

      this.dropboxShow = false; //定義存儲下拉框的顯示隱藏狀態(tài)
      this.defaultValue = ""; //定義村赤默認(rèn)選中的值
      this._creatElement(); //初始化后執(zhí)行創(chuàng)建元素方法
    },

    //創(chuàng)建下拉選擇框dom
    _creatElement() {
      //選擇框最外層的包裹元素
      let wrapEle = document.createElement("div");
      wrapEle.className = "my-select";

      //根據(jù)傳入的值獲取選擇框默認(rèn)的值和內(nèi)容
      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"); //選擇框默認(rèn)展示框
      let selectNameBox = document.createElement("span"); //選擇框展現(xiàn)的值ele
      selectNameBox.className = "select-selected-value";
      selectNameBox.id = "select-option";
      selectNameBox.innerText = this.defaultText; //將傳入的默認(rèn)值賦值
      let selectIcon = document.createElement("i"); //圖標(biāo)ele
      selectIcon.className = "arrow-down icon-select-arrow";
      //將span和角標(biāo)添加到外層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";
      //遍歷傳入的選項(xiàng)數(shù)組對象,生成下拉菜單的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掛載到當(dāng)前實(shí)例
      //this.wrapEle = wrapEle;   //最外層包裹元素
      this.eleSelect = selectWarpBox; //選擇框
      this.eleDrop = dropbox; //下拉框
      this.eleSpan = selectNameBox; //顯示文字的span節(jié)點(diǎn)

      //綁定事件處理函數(shù)
      this._bind(this.parentEle);
    },

    //點(diǎn)擊下拉框事件處理函數(shù)
    _selectHandleClick() {
      if (this.dropboxShow) {
        this._selectDropup();
      } else {
        this._selectDropdown();
      }
    },

    //收起下拉選項(xiàng)
    _selectDropup() {
      this.eleDrop.style.transform = "scale(1,0)";
      this.eleDrop.style.opacity = "0";
      this.eleSelect.className = "select-selection";
      this.dropboxShow = false;
    },

    //展示下拉選項(xiàng)
    _selectDropdown() {
      this.eleDrop.style.transform = "scale(1,1)";
      this.eleDrop.style.opacity = "1";
      this.eleSelect.className = "select-selection select-focus";
      this.dropboxShow = true;
    },

    //點(diǎn)擊下拉選項(xiàng)進(jìn)行賦值
    _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";
      //對點(diǎn)擊選中的其他所有兄弟元素修改class去除選中樣式
      this._siblingsDo(ele, function (ele) {
        if (ele) {
          ele.className = "select-item";
        }
      });
      this._selectDropup();
    },

    //node遍歷是否是子元素包裹元素
    _getTargetNode(ele, target) {
      //ele是內(nèi)部元素,target是你想找到的包裹元素
      if (!ele || ele === document) return false;
      return ele === target ? true : this._getTargetNode(ele.parentNode, target);
    },

    //兄弟元素遍歷處理函數(shù)
    _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);

    },

    //綁定下拉框事件處理函數(shù)
    _bind(parentEle) {
      let _this = this;
      //事件委托到最外層包裹元素進(jìn)行綁定處理
      parentEle.addEventListener("click", function (e) {
        const ele = e.target;
        
        //遍歷當(dāng)前點(diǎn)擊的元素,如果是選中框內(nèi)的元素執(zhí)行
        if (_this._getTargetNode(ele, _this.eleSelect)) {
          if (_this.dropboxShow) {
            _this._selectDropup();
          } else {
            _this._selectDropdown();
          }
        } else if (ele.className === "select-item") { //如果是點(diǎn)擊的下拉框的選項(xiàng)執(zhí)行
          _this._dropItemClick(ele);
        } else { //點(diǎn)擊其他地方隱藏下拉框
          _this._selectDropup();
        }

      });

    }

  };
  //將構(gòu)造函數(shù)掛載到全局window
  window.$Selector = Selector;
})(window, document);

到此,一個(gè)自定義下拉菜單就出爐了,下面是動態(tài)效果:

如何使用原生JS實(shí)現(xiàn)自定義下拉單選選擇框功能

至此,從css自定義的表單元素到下拉框元素都已經(jīng)自定義完畢,使用bootstrap的同學(xué)把這些加進(jìn)去就能基本保持各瀏覽器效果一致性和美觀性了,就到這吧先。

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“如何使用原生JS實(shí)現(xiàn)自定義下拉單選選擇框功能”這篇文章對大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

js
AI