elementUI使用vue-direction-key实现键盘上下左右bug解决办法

本文介绍了一个使用Vue-direction-key库实现输入框焦点在页面元素间切换的解决方案,特别针对Element UI的select和date组件存在的问题进行了修复。作者通过监听键盘按键事件,动态调整焦点,并处理select的展开、关闭以及date picker的隐藏,以实现流畅的导航效果。代码中包含了针对上下左右四个方向的焦点移动逻辑,并提供了具体的代码片段作为示例。
摘要由CSDN通过智能技术生成

最近要求输入框上下左右能实现输入框焦点切换的效果,在网上查了下决定使用vue-direction-key来实现功能,但是实际使用发现vue-direction-key配合element的select和date组件使用有问题,比如select无法展开、切换、关闭,然后对direction.on的方法进行修改,最后实现了功能。

页面部分代码,注意x和y必须严格从0开始加1,我没做跳多个的判断,select和date分别使用type,date还需要配置dateIndex和ref

<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm"
          v-if="dialogVisible">


          <section>
            <div class="row">
              <el-form-item label="筛选条件" label-width="100px">
                <el-input v-direction="{x: 0, y: 0,type:'input'}" v-model="searchPaient" placeholder="健康id,证件号,姓名,手机号"  @input="nameChange"
                  @click.native.stop="nameChange"></el-input>
                <div class="paientList" v-show="isShow && searchList.length>0">
                  <div class="item" v-for="item in searchList" :key="item.id" @click="setPaient(item)">
                    {{item.realName}}
                  </div>
                </div>
              </el-form-item>
            </div>
            <div class="title">
              基本信息
            </div>

            <div class="row">
              <div class="inputBox">
                <el-form-item label="姓名" prop="realName">
                  <el-input v-direction="{x: 0, y: 1,type:'input'}" v-model="ruleForm.realName"></el-input>
                </el-form-item>
              </div>
              <div class="inputBox">
                <el-form-item label="证件类型" prop="cardType">
                  <el-select v-direction="{x: 1, y: 1,type:'select'}" v-model="ruleForm.cardType" placeholder="" style="width: 120px;">
                    <el-option v-for="item in cardTypeArr" :key="item.standardCode" :label="item.dictName"
                      :value="item.standardCode">
                    </el-option>
                  </el-select>
                </el-form-item>
              </div>
              <div class="inputBox">
                <el-form-item label="证件号" prop="idCard">
                  <el-input v-direction="{x: 2, y: 1,type:'input'}" v-model="ruleForm.idCard" placeholder="" @input="getBir"></el-input>
                </el-form-item>
              </div>


            </div>
            <div class="row">
              <div class="inputBox">
                <el-form-item label="性别" prop="accountSex">
                  <el-select v-direction="{x: 0, y: 2,type:'select'}" v-model="ruleForm.accountSex" placeholder="" style="width: 100px;" @change="sexChange">
                    <el-option v-for="item in sexArr" :key="item.standardCode" :label="item.dictName"
                      :value="item.standardCode">
                    </el-option>
                  </el-select>
                </el-form-item>
              </div>
              <div class="inputBox">
                <el-form-item label="出生日期" prop="birthday">
                <!--   <el-input v-direction="{x: 2, y: 1,type:'input'}" v-model="ruleForm.idCard" placeholder="" @input="getBir" type="date"></el-input> -->
                 <el-date-picker v-direction="{x: 1, y: 2,type:'date',dateIndex:1}" ref="date1" v-model="ruleForm.birthday" type="date" placeholder="" style="width: 200px;"
                    @change="dateChange" value-format="yyyy-MM-dd" :picker-options="pickerBeginDateBefore" >
                  </el-date-picker>
                </el-form-item>
              </div>

修改direction.on代码

  created() {
    let direction = this.$getDirection()
    direction.on('keyup', (e, val) => {
      e.preventDefault()
      console.log($(document.activeElement).parents('.el-input,.el-select'));
      console.log(direction)
      let activeNode = $(document.activeElement).parents('.el-input,.el-select')[1] ? $(document.activeElement)
        .parents('.el-input,.el-select')[1] : $(document.activeElement).parents('.el-input,.el-select')[0];
      let nodeArrayActive;
      let x, y;
      let nodeArr = direction.nodeArray;
      nodeArr.forEach(item => {
        item.forEach((item2) => {
          if (item2.node == activeNode) {
            nodeArrayActive = item2;
            x = item2.value.x;
            y = item2.value.y;
          }
        })
      })
      // 右
      if (e.keyCode === 39) {
        x += 1;
        let nextIndex = nodeArr[y].findIndex(item => {
          return item.value.x == x && item.value.y == y
        })
        if (nextIndex != -1) {
          $(nodeArr[y][nextIndex].node).find('input').focus()
          if (nodeArr[y][nextIndex].value.type == 'select') {
            nodeArr[y][nextIndex].node["__vue__"].toggleMenu()
          }

          if(nodeArrayActive.value.type=='date'){

            this.$refs['date'+nodeArrayActive.value.dateIndex].hidePicker()

          }
          activeNode["__vue__"].blur();
        } else {
          x = 0;
          y += 1;
          if (nodeArr.length - 1 >= y) {
            let nextIndexRow = nodeArr[y].findIndex(item => {
              return item.value.x == x && item.value.y == y
            })
            console.log(nextIndexRow)
            if (nextIndexRow != -1) {
              $(nodeArr[y][nextIndexRow].node).find('input').focus();
              if (nodeArr[y][nextIndexRow].value.type == 'select') {
                nodeArr[y][nextIndexRow].node["__vue__"].toggleMenu()
              }
              if(nodeArrayActive.value.type=='date'){

                this.$refs['date'+nodeArrayActive.value.dateIndex].hidePicker()

              }
              activeNode["__vue__"].blur();
            } else {
              return;
            }
          }
        }
      }
      // 左
      if (e.keyCode === 37) {
        x -= 1;
        if (x >= 0) {
          let nextIndex = nodeArr[y].findIndex(item => {
            return item.value.x == x && item.value.y == y
          })
          if (nextIndex != -1) {

            $(nodeArr[y][nextIndex].node).find('input').focus();
            if (nodeArr[y][nextIndex].value.type == 'select') {
              nodeArr[y][nextIndex].node["__vue__"].toggleMenu()
            }
            if(nodeArrayActive.value.type=='date'){

              this.$refs['date'+nodeArrayActive.value.dateIndex].hidePicker()

            }

            activeNode["__vue__"].blur();

          } else {
            return

          }
        } else {
          y -= 1;
          if (y >= 0) {
            x = nodeArr[y][nodeArr[y].length - 1].value.x;
            let nextIndexRow = nodeArr[y].findIndex(item => {
              return item.value.x == x && item.value.y == y
            })
            console.log(nextIndexRow, x, y)
            if (nextIndexRow != -1) {
              $(nodeArr[y][nextIndexRow].node).find('input').focus();
              if (nodeArr[y][nextIndexRow].value.type == 'select') {
                nodeArr[y][nextIndexRow].node["__vue__"].toggleMenu()
              }
              if(nodeArrayActive.value.type=='date'){

                this.$refs['date'+nodeArrayActive.value.dateIndex].hidePicker()

              }

              activeNode["__vue__"].blur();
            }
          }
        }
      }
      // 上
      if (e.keyCode === 38) {
        y -= 1;
        if (y >= 0) {
          let nextIndexRow = nodeArr[y].findIndex(item => {
            return item.value.x == x && item.value.y == y
          })
          if (nextIndexRow != -1) {
            $(nodeArr[y][nextIndexRow].node).find('input').focus();
            if (nodeArr[y][nextIndexRow].value.type == 'select') {
              nodeArr[y][nextIndexRow].node["__vue__"].toggleMenu()
            }
            if(nodeArrayActive.value.type=='date'){

              this.$refs['date'+nodeArrayActive.value.dateIndex].hidePicker()

            }

            activeNode["__vue__"].blur();
          } else {
            x = 0;
            let nextIndexCol = nodeArr[y].findIndex(item => {
              return item.value.x == x && item.value.y == y
            })
            if (nextIndexCol != -1) {
              $(nodeArr[y][nextIndexCol].node).find('input').focus();
              if (nodeArr[y][nextIndexCol].value.type == 'select') {
                nodeArr[y][nextIndexCol].node["__vue__"].toggleMenu()
              }
              if(nodeArrayActive.value.type=='date'){

                this.$refs['date'+nodeArrayActive.value.dateIndex].hidePicker()

              }

              activeNode["__vue__"].blur();
            }
          }
        }

      }
      // 下
      if (e.keyCode === 40) {
        y += 1;
        if (y <= nodeArr.length - 1) {
          let nextIndexRow = nodeArr[y].findIndex(item => {
            return item.value.x == x && item.value.y == y
          })
          if (nextIndexRow != -1) {
            $(nodeArr[y][nextIndexRow].node).find('input').focus();
            if (nodeArr[y][nextIndexRow].value.type == 'select') {
              nodeArr[y][nextIndexRow].node["__vue__"].toggleMenu()
            }
            if(nodeArrayActive.value.type=='date'){

              this.$refs['date'+nodeArrayActive.value.dateIndex].hidePicker()

            }

            activeNode["__vue__"].blur();
          } else {
            x = 0;
            let nextIndexCol = nodeArr[y].findIndex(item => {
              return item.value.x == x && item.value.y == y
            })
            if (nextIndexCol != -1) {
              $(nodeArr[y][nextIndexCol].node).find('input').focus();
              if (nodeArr[y][nextIndexCol].value.type == 'select') {
                nodeArr[y][nextIndexCol].node["__vue__"].toggleMenu()
              }
              if(nodeArrayActive.value.type=='date'){

                this.$refs['date'+nodeArrayActive.value.dateIndex].hidePicker()

              }

              activeNode["__vue__"].blur();
            }
          }
        }
      }
    })
  },

由于是项目比较急搞得,有一些地方处理没有太好,基本就只是实现自己的目的,但基本通过这种方法能实现功能,基本思路就是通过节点和direction的nodeArr去操作聚焦,失焦,关闭,其中date我发现只能通过强行去操作ref去关闭,否则使用nodeArrayActive[“vue”]关闭一次后,就调用不了hidePicker方法,至于其他的框和类型,暂时还没做,以后有时间再做修改吧,只是提供一个思路,不一定适用所有人项目

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值