el-select既能选择又能输入,并且再次点击时能接着编辑
1)el-select添加filterable和之后可以输入内容;2)再次输入时会将原来的内容变成提示,用户体验不好,因此需要找到办法将值重新赋给内部的input输入框,此处采用的方式将值重新赋给input输入框。3)使用之后可以确保按Enter键时能将内容输入,但是用户体验不好,因此使用方式将input输入框中的值实时赋值给绑定值select,用完记得在beforeDestroy()中移除监听。
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键时能将内容输入,但是用户体验不好,因此需要监听blur事件的方式将input输入框中的值赋值给绑定值select。
4)点击el-select输入框时下拉框会隐藏,用户体验非常不好,此处使用巧妙方法this.$refs.select.toggleMenu()将下拉框弹出。此处使用mousedown事件而非click事件的原因是click事件会在visible-change事件之后触发,而mousedown则在visible-change事件之前触发。
5)bug:当输入的值与optionsSelect中的value值一样时会有bug,两者都会被选中,此为el-select本身就有的bug。
3.代码
<template>
<el-select
ref="select"
v-model="select"
filterable
allow-create
default-first-option
@blur="inputBlur()"
@mousedown.native="click()"
@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 {
isClicked: false, // 是否触发el-select输入框的click事件
select: '',
optionsSelect: [{
label: '黄金糕123',
value: '黄金糕'
},
{
label: '双皮奶123',
value: '双皮奶'
}]
}
},
methods: {
inputBlur() {
this.$nextTick(() => {
this.changeValue()
})
},
changeValue() {
let isIn = false
const val = this.$refs.select.$children[0].$refs.input.value
for (let i = 0; i < this.optionsSelect.length; i++) {
if (val === this.optionsSelect[i].label) {
this.select = this.optionsSelect[i].value
isIn = true
break
}
}
if (!isIn) {
this.select = val
}
},
visibleChange(val) {
if (val) { // 下拉框展开
this.isClicked = false
const selectionStart = this.$refs.select.$children[0].$refs.input.selectionStart
this.$nextTick(() => {
const inputElement = this.$refs.select.$children[0].$refs.input
inputElement.value = this.getSelectLabel()
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 {
if (this.$refs.select.$children[0].$refs.input === document.activeElement) { // 不隐藏下拉框,只有失去焦点会隐藏
if (this.isClicked) { // 主要解决点击el-select输入框不会触发blur事件
this.changeValue()
this.$refs.select.toggleMenu()
this.isClicked = false
}
} else {
this.changeValue()
}
}
},
getSelectLabel() {
for (let i = 0; i < this.optionsSelect.length; i++) {
if (this.select === this.optionsSelect[i].value) {
return this.optionsSelect[i].label
}
}
return this.select
},
click() {
this.isClicked = true
}
}
}
</script>
更多推荐
所有评论(0)