起因
最近的业务里有个需求,就是要实现自动填充,这个在elment-plus也有对应的组件,但是自己希望自定义input的样式,所以采用了input+el-dropdown的做法来实现自动填充效果。
出现的bug
<script setup>
defineProps({
msg: String,
})
</script>
<template>
<el-dropdown>
<input type="text">
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>Action 1</el-dropdown-item>
<el-dropdown-item>Action 2</el-dropdown-item>
<el-dropdown-item>Action 3</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<style scoped>
.read-the-docs {
color: #888;
}
</style>
效果大概是这样的
这里的input处于eldropdown之中是无法输入空格的。
解决方案
在网上找了很多文章,不过大多是教怎么禁止在input中输入空格(可能我找的关键词有问题),后来找到这篇文章,这位遇到的问题是dropdown-item阻断了keydown时间(奇怪的是,我尝试把input放到el-dropdown-item里时,不仅能正常输入还能输入空格qwq),不过这也给了我一些启发。
我们可以监听input的键盘事件,然后在输入空格时,手动把空格加上去。
像这样
<script setup>
defineProps({
msg: String,
})
function doSomething(){
console.log('zhongqiux')
}
</script>
<template>
<el-dropdown placement="bottom-start" :hide-on-click="false">
<input type="text" @keyup.space="doSomething">
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>Action 1</el-dropdown-item>
<el-dropdown-item>Action 2</el-dropdown-item>
<el-dropdown-item>Action 3</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<style scoped>
.read-the-docs {
color: #888;
}
</style>
原理可行,结果如下
<script setup>
import { ref } from 'vue'
defineProps({
msg: String,
})
const word = ref('');
function doSomething(){
word.value += ' '
}
</script>
<template>
<el-dropdown placement="bottom-start" :hide-on-click="false">
<input v-model="word" type="text" @keyup.space="doSomething">
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>Action 1</el-dropdown-item>
<el-dropdown-item>Action 2</el-dropdown-item>
<el-dropdown-item>Action 3</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<style scoped>
.read-the-docs {
color: #888;
}
</style>
不过现在又有了另一个问题,那就是输入空格之后,input就会失去focus,推测是因为dropdown接收到空格之后自动Blur,最后非常曲折的实现了输入空格以及控制下拉框出现的时机
<script setup>
import { ref } from 'vue'
defineProps({
msg: String,
})
const word = ref('');
const input = ref(null)
const drop = ref(null)
const dropStatus = ref(true)
function doSomething(){
word.value += ' '
setTimeout(()=>{ input.value.focus() },300)
}
function open(){
dropStatus.value = false;
drop.value.handleOpen()
}
function close(open){
if(!open){
dropStatus.value = true;
drop.value.handleOpen()
}
}
</script>
<template>
<el-dropdown placement="bottom-start" ref="drop" :disabled="dropStatus" @visible-change="close">
<input v-model="word" ref="input" type="text" @keyup.space="doSomething()" style="outline: none;">
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>Action 1</el-dropdown-item>
<el-dropdown-item>Action 2</el-dropdown-item>
<el-dropdown-item>Action 3</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-button @click="open">提示</el-button>
</template>
<style scoped>
.read-the-docs {
color: #888;
}
</style>