<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          組件封裝之輸入框下拉列表

          共 24154字,需瀏覽 49分鐘

           ·

          2021-04-09 13:18

          作者:Tokiya

          來源:SegmentFault 思否社區(qū)

          前言


          項目開發(fā)的時候剛好遇到一個需求,需要在輸入框輸入名字的時候,彈出相應的人員列表提供選擇,然后將數(shù)據(jù)賦值給輸入框。項目是使用iview組件的,一開始想著在自定義iview的下拉選擇,后來發(fā)現(xiàn)效果并不理想。為了實現(xiàn)功能,就在iview輸入框的基礎上進行了組件封裝,下面就來講下組件封裝的過程。


          思路:


          對于組件封裝,首先需要確定功能,組件的整體結(jié)構,后面再去處理組件的數(shù)據(jù)交互邏輯。


          過程:


          組件的結(jié)構以及樣式:

          話不多說,先把組件基本的結(jié)構樣式貼出來。

          組件布局:

          <template>
              <div class="selectInput">
                  <div class="input-box">
                      <Input type="text" />
                  </div>
                  <div class="input-dropdown">
                      <div class="dropdown-title">
                          您可能需要查找
                      </div>
                      <div class="dropdown-content">
                          <ul class="content-list">
                              <li class="list-item">
                                  <span class="item-avatar">李</span>
                                  <span class="item-name">李四</span>
                              </li>
                          </ul>
                          <!-- 沒有數(shù)據(jù)時的提示信息 -->
                          <div class="content-msg">
                              暫無數(shù)據(jù)
                          </div>
                      </div>
                  </div>
              </div>
          </template>

          既然是輸入下拉,就需要一個輸入框以及一個下拉列表。

          樣式:

          .selectInput {
              position: relative;
              .input-dropdown {
                  min-width: 200px;
                  position: absolute;
                  top: 35px;
                  left: 0;
                  border: 1px solid #cfcfcf;
                  border-radius: 5px;
                  .dropdown-title {
                      padding: 5px 10px;
                      color: #e1e1e1;
                      background-color: #f8f8f8;
                  }
                  .dropdown-content {
                      .content-list {
                          margin: 0;
                          padding: 0;
                          .list-item {
                              margin: 0;
                              padding: 5px 10px ;
                              list-style: none;
                              &:hover {
                                  cursor: pointer;
                                  background-color: #f7f5f5;
                              }
                              .item-avatar {
                                  display: inline-block;
                                  width: 30px;
                                  height: 30px;
                                  line-height: 30px;
                                  color: #ffffff;
                                  background-color: #b6c4de;
                                  border-radius: 50%;
                                  text-align: center;
                                  margin-right: 10px;
                              }
                              .item-name {
                                  display: inline-block;
                                  color: #666666;
                              }
                          }
                      }
                      .content-msg {
                          padding: 10px;
                          color: #cccccc;
                      }
                  }
              }
          }

          寫完布局以及樣式之后的效果:

          組件的功能邏輯:


          1. 確定父子組件數(shù)據(jù)傳遞的props
          props: {
              // 父組件傳遞的輸入框初始值
              value: {
                  type: String,
                  default: ''
              },
              // 下拉列表的標題
              dropdownTitle: {
                  type: String,
                  default: '您可能要找'
              },
              // 下拉列表搜索數(shù)據(jù)為空時的提示
              dropdownMsg: {
                  type: String,
                  default: '數(shù)據(jù)為空!'
              },
              // 下拉列表的初始數(shù)組
              dropdownList: {
                  type: Array,
                  default: () => []
              },
              // 輸入框的提示
              placeholder: {
                  type: String,
                  default: '請輸入名字'
              },
          }
          2. 定義組件的data
          data() {
              return {
                  //  控制下拉列表顯示
                  dropdownShow: false,
                  //  控制下拉列表數(shù)據(jù)為空提示顯示
                  dropdownMsgShow: false,
                  //  輸入框值
                  inputValue: '',
                  //  搜索后的下拉列表,用于渲染下拉
                  searchDataList: []
              }
          }
          3. 下拉列表的搜索邏輯
          <template>
              <div class="selectInput">
                  <div class="input-box">
                      <Input :placeholder="placeholder" v-model="inputValue" @input.native="handleInput" type="text" />
                  </div>
                  <div v-show="dropdownShow" class="input-dropdown">
                      <div class="dropdown-title">
                          {{ dropdownTitle }}
                      </div>
                      <div class="dropdown-content">
                          <ul class="content-list">
                              <li v-for="(item, index) in searchDataList" :key="index" @click="handleChoose(item.name)" class="list-item">
                                  <span class="item-avatar">{{ item.avatar }}</span>
                                  <span class="item-name">{{ item.name }}</span>
                              </li>
                          </ul>
                          <!-- 沒有數(shù)據(jù)時的提示信息 -->
                          <div v-show="dropdownMsgShow" class="content-msg">
                              {{ dropdownMsg }}
                          </div>
                      </div>
                  </div>
              </div>
          </template>

          通過dropdownShow去控制下拉列表的顯示隱藏,給輸入框綁定一個inputValue值和一個input事件。

          // 輸入框輸入處理函數(shù)
          handleInput: debounce(function () {
              let _this = this;
              _this.searchDataList = [];
              if (_this.inputValue === '') {
                  _this.dropdownShow = false;
              } else {
                  _this.dropdownList.map(v => {
                      if (v.name.indexOf(_this.inputValue) >= 0) {
                          _this.searchDataList.push(v);
                      }
                  });
                  _this.searchDataList.length > 0 ? _this.dropdownMsgShow = false : _this.dropdownMsgShow = true;
                  _this.dropdownShow = true;
              }
          })

          handleInput我做了防抖處理,在這個函數(shù)里面通過監(jiān)聽輸入框輸入事件,判斷輸入框的inputValue是否為空,若為空則直接隱藏下拉列表。不為空則循環(huán)迭代從父組件傳遞過來的dropdownList,并將符合條件的item存進searchDataList,然后在組件中通過v-for渲染出數(shù)據(jù)。
          最后通過判斷
          searchDataList的長度給dropdownMsgShow賦值,來控制搜索數(shù)據(jù)的提示信息。

          4. 搜索后的點擊選擇處理

          給下拉列表的每一項li綁定一個點擊事件handleChoose。

          // 下拉選擇處理函數(shù)
          handleChoose: function (val) {
              let _this = this;
              _this.inputValue = val; 
              _this.dropdownShow = false;
          }

          點擊之后對輸入框進行賦值,并隱藏下拉列表。

          5. 給組件添加一個clickoutside指令

          自定義clickoutside指令,當點擊組件外的區(qū)域時隱藏下拉列表。

          directives: {
              // 自定義指令用于處理點擊組件區(qū)域之外的click事件
              clickoutside: {
                  bind(el, binding, vnode) {
                      function documentHandler(e) {
                          if (el.contains(e.target)) {
                              return false;
                          }
                          if (binding.expression) {
                              binding.value(e);
                          }
                      }
                      el.__vueClickOutSize__ = documentHandler;
                      document.addEventListener("click", documentHandler);
                  },
                  unbind(el, binding) {
                      document.removeEventListener("click", el.__vueClickOutSize__);
                          delete el.__vueClickOutSize__;
                  },
              },
          },

          給指令綁定一個關閉事件handleClose。

          // 下拉列表隱藏處理函數(shù)
          handleClose: function() {
              let _this = this;
              if (_this.dropdownShow) {
                  if (_this.searchDataList.length === 1) {
                      _this.inputValue = _this.searchDataList[0].name;
                  } else {
                      _this.inputValue = '';
                  }
              }
              _this.dropdownShow = false;
          },

          在這個函數(shù)里我做了一個處理,當點擊的時候,搜索列表有數(shù)據(jù)時,會默認選中第一個,否則清空輸入框。

          關于函數(shù)防抖以及clickoutside,網(wǎng)上有大佬發(fā)了一些關于這些的文章,我在這里就不進行贅述了。

          至此,組件封裝完成,組件的大體思路是這樣子,具體的邏輯處理可以根據(jù)實際情況進行相應的調(diào)整。

          最后附上整個組件的代碼:
          調(diào)用代碼:

          <template>
              <div id="blog">
                  <select-input :dropdownList="personnelList"></select-input>
              </div>
          </template>
          <script>
          /* 引入輸入下拉組件 */
          import selectInput from './component/selectInput';

          export default {
              name: 'blog',
              components: {
                  selectInput
              },
              data() {
                  return {
                      personnelList: [
                          {
                              avatar: '張',
                              name: '張三'
                          },
                          {
                              avatar: '李',
                              name: '李四'
                          },
                          {
                              avatar: '王',
                              name: '王五'
                          },
                          {
                              avatar: '趙',
                              name: '趙六'
                          },
                          {
                              avatar: '李',
                              name: '李師師'
                          }
                      ]
                  }
              },
              methods: {

              },
              created() {

              },
              mounted() {

              }
          }
          </script>
          <style lang="less" scoped>
          #blog {
              padding: 50px;
              width: 500px;
              margin: 100px auto 0;
              background: #ffffff;
              height: 500px;
          }
          </style>

          組件代碼:

          <template>
              <div v-clickoutside="handleClose" class="selectInput">
                  <div class="input-box">
                      <Input :placeholder="placeholder" v-model="inputValue" @input.native="handleInput" type="text" />
                  </div>
                  <div v-show="dropdownShow" class="input-dropdown">
                      <div class="dropdown-title">
                          {{ dropdownTitle }}
                      </div>
                      <div class="dropdown-content">
                          <ul class="content-list">
                              <li v-for="(item, index) in searchDataList" :key="index" @click="handleChoose(item.name)" class="list-item">
                                  <span class="item-avatar">{{ item.avatar }}</span>
                                  <span class="item-name">{{ item.name }}</span>
                              </li>
                          </ul>
                          <div v-show="dropdownMsgShow" class="content-msg">
                              {{ dropdownMsg }}
                          </div>
                      </div>
                  </div>
              </div>
          </template>

          <script>


          點擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開更多互動和交流,掃描下方”二維碼“或在“公眾號后臺回復“ 入群 ”即可加入我們的技術交流群,收獲更多的技術文章~

          - END -


          瀏覽 42
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99爱视频 | 91久久国产视频 | 久久久久久亚洲精品 | 国产精品成人电影 | 国产精品久久久久久爽爽爽麻豆色哟哟 |