1.实现效果
2.实现原理
1)el-select添加filterable和allow-create之后可以输入内容;
2)再次输入时会将原来的内容变成提示,用户体验不好,因此需要找到办法将值重新赋给内部的input输入框,此处采用this.$refs.select.$children[0].$refs.input.value = this.select的方式将值重新赋给input输入框。
3)使用default-first-option之后可以确保按Enter键时能将内容输入,但是用户体验不好,因此使用this.$refs.select.$children[0].$refs.input.addEventListener('input', this.inputValue, false)方式将input输入框中的值实时赋值给绑定值select,用完记得在beforeDestroy()中移除监听。
3.代码
<template>
<el-select
ref="select"
v-model="select"
filterable
allow-create
default-first-option
@visible-change="(val) => visibleChange(val)">
<el-option
v-for="item in optionsSelect"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
</template>
<script>
export default {
name: 'SelectInput',
data() {
return {
select: '',
optionsSelect: [{
label: '黄金糕',
value: '黄金糕'
},
{
label: '双皮奶',
value: '双皮奶'
}]
}
},
mounted() {
this.$refs.select.$children[0].$refs.input.addEventListener('input', this.inputValue, false)
},
beforeDestroy() {
this.$refs.select.$children[0].$refs.input.removeEventListener('input', this.inputValue, false)
},
methods: {
inputValue() {
this.$nextTick(() => {
this.select = this.$refs.select.$children[0].$refs.input.value
})
},
visibleChange(val) {
if (val) { // 下拉框展开
const selectionStart = this.$refs.select.$children[0].$refs.input.selectionStart
console.log(selectionStart)
this.$nextTick(() => {
const inputElement = this.$refs.select.$children[0].$refs.input
inputElement.value = this.select
inputElement.setSelectionRange(selectionStart, selectionStart)
inputElement.focus()
// 计算滚动位置
const characterWidth = inputElement.scrollWidth / inputElement.value.length
const scrollPosition = (selectionStart + 1) * characterWidth - inputElement.offsetWidth / 2
// 确保滚动位置不超过边界
const maxScrollPosition = inputElement.scrollWidth - inputElement.offsetWidth
inputElement.scrollLeft = Math.min(maxScrollPosition, scrollPosition)
})
} else { // 下拉框关闭
this.$nextTick(() => {
if (this.$refs.select.$children[0].$refs.input === document.activeElement) {
this.$refs.select.toggleMenu()
}
})
}
}
}
}
</script>