Javascript 自定义选择元素的模糊上的Vuejs无效
场景 我已经构建了自定义的自动完成选择组件,它可以在其中自动完成,但是另外,如果没有找到结果,我们可以添加新的值。(我发现在vue选择模块中不可能) 问题 我尝试使用@blur,但如果单击该项,菜单将关闭。 我将自定义div作为一个项目列表,用于选择在焦点位于文本字段时切换的项目。如果我删除模糊,效果会很好,但不会关闭,我会在文本字段外单击。 我复制了用于处理向上键、向下键、键盘输入、滚动、处理vue select选择指针的函数 代码Javascript 自定义选择元素的模糊上的Vuejs无效,javascript,vue.js,Javascript,Vue.js,场景 我已经构建了自定义的自动完成选择组件,它可以在其中自动完成,但是另外,如果没有找到结果,我们可以添加新的值。(我发现在vue选择模块中不可能) 问题 我尝试使用@blur,但如果单击该项,菜单将关闭。 我将自定义div作为一个项目列表,用于选择在焦点位于文本字段时切换的项目。如果我删除模糊,效果会很好,但不会关闭,我会在文本字段外单击。 我复制了用于处理向上键、向下键、键盘输入、滚动、处理vue select选择指针的函数 代码 <template> <
<template>
<div class="vselect">
<div class="form-group">
<label>{{label}}</label>
<p class="control has-icon has-icon-right">
<input ref="selected" @keyup="filterSelect($event)" @focus="onFocus" v-model="mutableValue" type="text" class="form-control"
@keydown.up.prevent="onKeyUp" @keydown.down.prevent="onKeyDown" @keydown.enter.prevent="onKeyEnter" @blur="onBlur">
</p>
</div>
<div ref="dropdown" class="my-dropdown" v-show="toggled" v-if="options">
<div v-for="(item,index) in filterList" :class="{'my-dropdwon--item':true,active:index === pointer}" @click="handleItemClick(item)"
@mouseover="pointer = index">{{item}}</div>
</div>
</div>
</template>
<script>
export default {
name: 'VSelect',
props: {
'options': Array,
'label': String,
'value': String,
},
data() {
return {
selected: null,
toggled: false,
filterList: [],
mutableValue: null,
mutableOptions: [],
pointer: 0
}
},
methods: {
filterSelect: function (key) {
if (!this.toggled) this.toggled = !this.toggled;
let oldArr = this.options;
if (this.mutableValue && this.mutableValue.length <= 0)
this.filterList = this.mutableOptions;
else if (key.key.length == 1 || key.key == 'Backspace') {
oldArr = oldArr.filter(item => {
if (item.toLowerCase().includes(this.mutableValue.toLowerCase()))
return true;
})
this.filterList = oldArr;
//console.log('type', this.filterList)
}
// if (key.key == 'Enter')
// this.toggled = !this.toggled;
this.$emit('input', this.mutableValue);
},
handleItemClick: function (item) {
this.mutableValue = item;
this.$emit('input', item);
this.toggled = !this.toggled;
},
onFocus: function () {
this.$refs.dropdown.scrollTop = 0;
this.toggled = !this.toggled;
},
onBlur: function () {
this.handleItemClick(this.mutableValue)
this.$refs.selected.blur();
},
onKeyUp: function () {
if (this.pointer > 0) this.pointer--;
if (this.maybeAdjustScroll) {
this.maybeAdjustScroll()
}
},
onKeyDown: function () {
if (this.pointer < this.options.length && this.filterList.length) this.pointer++;
if (this.pointer == this.options.length) this.pointer = 0;
if (this.maybeAdjustScroll) {
this.maybeAdjustScroll()
}
},
onKeyEnter: function () {
//console.log(this.filterList.length> 0);
if(this.filterList.length > 0)
this.handleItemClick(this.filterList[this.pointer])
this.$refs.selected.blur();
this.$emit('input', this.mutableValue);
this.toggled = false;
},
maybeAdjustScroll() {
let pixelsToPointerTop = this.pixelsToPointerTop()
let pixelsToPointerBottom = this.pixelsToPointerBottom()
//console.log(pixelsToPointerTop,pixelsToPointerBottom);
if (pixelsToPointerTop <= this.viewport().top) {
return this.scrollTo(pixelsToPointerTop)
} else if (pixelsToPointerBottom >= this.viewport().bottom) {
return this.scrollTo(this.viewport().top + this.pointerHeight())
}
},
pixelsToPointerTop() {
let pixelsToPointerTop = 0
if (this.$refs.dropdown && this.$refs.dropdown.children) {
for (let i = 0; i < this.pointer; i++) {
pixelsToPointerTop += this.$refs.dropdown.children[i].offsetHeight
}
}
return pixelsToPointerTop
},
pixelsToPointerBottom() {
return this.pixelsToPointerTop() + this.pointerHeight()
},
pointerHeight() {
let element = this.$refs.dropdown ? this.$refs.dropdown.children[this.pointer] : false
return element ? element.offsetHeight : 0
},
viewport() {
return {
top: this.$refs.dropdown ? this.$refs.dropdown.scrollTop : 0,
bottom: this.$refs.dropdown ? this.$refs.dropdown.offsetHeight + this.$refs.dropdown.scrollTop : 0
}
},
scrollTo(position) {
//console.log(position);
return this.$refs.dropdown ? this.$refs.dropdown.scrollTop = position : null
},
},
mounted() {
this.filterList = this.options;
},
watch: {
value(val) {
this.mutableValue = val
},
options(val) {
this.mutableOptions = val
},
pointer() {
this.maybeAdjustScroll()
}
}
}
</script>
<style scoped>
.vselect {
display: block;
position: relative;
}
.my-dropdown {
width: 100%;
background: #f7f7f7;
margin-top: 0.1rem;
border: 1px solid #ced4da;
border-radius: 3px;
transition: all 0.5s;
position: absolute;
z-index: 1;
max-height: 10rem;
overflow: auto
}
.my-dropdwon--item {
padding: 0.5rem;
width: 100%;
transition: all 0.5s;
}
.active {
cursor: pointer;
background-color: rgb(223, 221, 221);
}
/* .my-dropdwon--item:hover {
cursor: pointer;
background-color: rgb(223, 221, 221);
} */
.form-group {
margin-bottom: 0px;
}
.control.has-icon has-icon-right {
margin-bottom: 0px;
}
.form-group>p {
margin-bottom: 0px;
}
</style>
{{label}}
{{item}}
导出默认值{
名称:“VSelect”,
道具:{
“选项”:数组,
“标签”:字符串,
“值”:字符串,
},
数据(){
返回{
选中:空,
切换为:false,
过滤器列表:[],
可变值:null,
可变选项:[],
指针:0
}
},
方法:{
过滤器选择:功能(键){
如果(!this.toggled)this.toggled=!this.toggled;
设oldArr=this.options;
if(this.mutableValue&&this.mutableValue.length{
if(item.toLowerCase().includes(this.mutableValue.toLowerCase()))
返回true;
})
this.filterList=oldArr;
//console.log('type',this.filterList)
}
//如果(key.key=='Enter')
//this.toggled=!this.toggled;
this.$emit('input',this.mutableValue);
},
handleItemClick:函数(项){
this.mutableValue=项目;
此.$emit('输入',项);
this.toggled=!this.toggled;
},
onFocus:function(){
这是。$refs.dropdown.scrollTop=0;
this.toggled=!this.toggled;
},
onBlur:function(){
this.handleItemClick(this.mutableValue)
这是.$refs.selected.blur();
},
onKeyUp:函数(){
如果(this.pointer>0)this.pointer--;
如果(此.maybeAdjustScroll){
this.maybeAdjustScroll()
}
},
onKeyDown:函数(){
如果(this.pointer0);
如果(this.filterList.length>0)
this.handleItemClick(this.filterList[this.pointer])
这是.$refs.selected.blur();
this.$emit('input',this.mutableValue);
this.toggled=false;
},
maybeAdjustScroll(){
设pixelsToPointerTop=this.pixelsToPointerTop()
设pixelsToPointerBottom=this.pixelsToPointerBottom()
//log(pixelsToPointerTop,pixelsToPointerBottom);
如果(pixelsToPointerTop=this.viewport().bottom){
返回this.scrollTo(this.viewport().top+this.pointerHeight())
}
},
pixelsToPointerTop(){
设pixelsToPointerTop=0
if(this.$refs.dropdown&&this.$refs.dropdown.children){
for(设i=0;i<div v-for="(item,index) in filterList"
:class="{'my-dropdwon--item':true,active:index === pointer}"
@mousedown="handleItemClick(item)"
@mouseover="pointer = index">
{{item}}
</div>