最近要求输入框上下左右能实现输入框焦点切换的效果,在网上查了下决定使用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方法,至于其他的框和类型,暂时还没做,以后有时间再做修改吧,只是提供一个思路,不一定适用所有人项目