Vue element下拉菜單實(shí)現(xiàn)鍵盤(pán)事件上下移

需求

提高用戶體驗(yàn)感,輸入框自動(dòng)聚焦并鍵盤(pán)控制下拉菜單的選項(xiàng)上下移
效果如圖:


初期使用的el-dropdown下拉菜單,組件默認(rèn)可鍵盤(pán)上下移

<el-dropdown
              v-if="authoritys.length > 0"
              trigger="click"
              @visible-change="toggleSchoolDrop"
              @command="_changeSchool"
            >
            <el-dropdown-menu slot="dropdown">
                <el-input
                  v-model="searchSchoolName"
                  clearable
                  class="school-input"
                  size="mini"
                  :placeholder="$t('el.input.placeholder')"
                  @input="searchSchool"
                />
                <div class="school-menu-list">
                  <el-dropdown-item
                    v-for="(s,i) in authoritysList"
                    v-show="!s.isHide"
                    :key="i"
                    :command="s.id"
                  >
                    {{ i < 9 ? `0${i + 1}` : i + 1 }}. {{ s.name }}
                  </el-dropdown-item>
                </div>
              </el-dropdown-menu>
 </el-dropdown> 

但是鍵盤(pán)按上下移不生效.
可能因?yàn)槲业膃l-dropdown-item是由數(shù)組遍歷出來(lái)的,文檔的菜單是寫(xiě)死的.
換成el-popover組件,內(nèi)部用ul和li實(shí)現(xiàn)遍歷菜單.

 <el-popover
    v-if="authoritys.length > 0"
    v-model="visible"
    trigger="click"
    @visible-change="toggleSchoolDrop"
  >
 <el-input
      v-model="searchSchoolName"
      clearable
      class="school-input mr-b-m"
      size="mini"
      :placeholder="$t('el.input.placeholder')"
      @input="searchSchool"
    />
    <ul
      id="school-menu-list"
      class="school-menu-list"
    >
      <li
        v-for="(s,i) in authoritysList"
        v-show="!s.isHide"
        :key="i"
        class="result-option"
        :class="{'is-active': i===activeIndex,'selectActive': i===selectIndex}"
        @mouseover="_handleMouseOver(i)"
        @click="_changeSchool(s.id,i)"
      >
      {{ i < 9 ? `0${i + 1}` : i + 1 }}. {{ s.name }}
      </li>
    </ul>
  </el-popover>

后續(xù)需要在input框自動(dòng)聚焦后再觸發(fā)鍵盤(pán)上下移事件.
實(shí)現(xiàn)自動(dòng)聚焦,首先想到的方法是 給el-input 添加ref,獲取后調(diào)用focus()

<el-input
      placeholder="請(qǐng)輸入內(nèi)容"
      v-model="value"
      clearable
      @keyup.enter.native="confirm"
      ref="sInput"
    >
this.$refs.sInput.focus()

但是不生效,
后續(xù)查看element官方文檔可用popover的show event手動(dòng)給el-input獲取焦點(diǎn)

<el-popover placement="bottom" width="200" trigger="manual" v-model="visible" @show="onShow">
    <el-input
      placeholder="請(qǐng)輸入內(nèi)容"
      v-model="value"
      clearable
      @keyup.enter.native="confirm"
      ref="sInput"
    >
</el-popover>

methods: {
      onShow () {
        this.$refs.sInput.focus()
      }
}

還是不生效,
對(duì)焦需要下拉打開(kāi)后執(zhí)行,也就是dom更新后所以添加 this.$nextTick生效

methods: {
      onShow () {
          this.$nextTick(() => {
              this.$refs.sInput.focus()
           });
      }
}

完成搜索輸入框的自動(dòng)對(duì)焦后添加鍵盤(pán)事件,
添加的鍵盤(pán)事件讓用戶看到選擇的選項(xiàng)樣式變化以外,滾輪是不會(huì)變動(dòng)的,
繼續(xù)提升用戶體驗(yàn)感,需要讓滾輪隨著用戶的操作而滑動(dòng)

 <el-input
      ref="searchSchool"
      v-model="searchSchoolName"
      clearable
      class="school-input mr-b-m"
      size="mini"
      :placeholder="$t('el.input.placeholder')"
      @input="searchSchool"
      @keyup.enter.native="_handleEnter(selectIndex)"
      @keyup.up.native="_handleUp"
      @keyup.down.native="_handleDown"
    />
methods: {
    _handleUp(){
            //  實(shí)現(xiàn)對(duì)樣式的替換
            this.selectIndex = this.selectIndex === 0 ? this.authoritysList.length - 1 : this.selectIndex - 1;

            let selectNum = this.selectIndex + 1;
            let schoolMenuList = document.getElementById("school-menu-list");
            let intervalTop = schoolMenuList.scrollTop;

            //  實(shí)現(xiàn)在用戶操作是,滾輪隨著上下移的動(dòng)
            if (selectNum * 35 <= intervalTop){

                schoolMenuList.scrollTop = (selectNum - 1) * 35;

            } else if (selectNum * 35 <= intervalTop + schoolMenuList.offsetHeight){

                schoolMenuList.scrollTop = intervalTop;

            } else if (selectNum * 35 > intervalTop){

                schoolMenuList.scrollTop = selectNum * 35;
            }

        },
    _handleDown(){
            this.selectIndex = this.selectIndex < this.authoritysList.length - 1 ? this.selectIndex + 1 : 0;

            let selectNum = this.selectIndex + 1;
            let schoolMenuList = document.getElementById("school-menu-list");
            let intervalTop = schoolMenuList.scrollTop;

            if (selectNum * 35 <= intervalTop){

                schoolMenuList.scrollTop = (selectNum - 1) * 35;

            } else if (selectNum * 35 <= intervalTop + schoolMenuList.offsetHeight){

                schoolMenuList.scrollTop = intervalTop;

            } else if (selectNum * 35 > intervalTop){

                schoolMenuList.scrollTop = selectNum * 35 - schoolMenuList.offsetHeight;
            }

        }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容