Vue 封装下拉框支持汉字、拼音和数字不同类型搜索
项目需求下拉框根据名称、编码和简拼搜索,许多现有组件不符合需要,因此自己封装了一个组件,代码如下:
父组件使用:
<selectDefault :placeholder="'请选择'" :bindValue.sync="value" :optionList="list" :label="'name'" :number="'number'" :english="'pinyin'" :values="'code'"> </selectDefault>
子组件:
<template> <div class="selfSelect" id="selfSelectA" @blur="isShow=false"> <input type="text" v-model="value" @focus="inputFocus" :placeholder="placeholder" @input="valueInput" @keyup="inputKey"> <ul v-if="isShow"> <li tabindex="1" :class="{ active: num === index,selectItems:'selectItems' }" v-for="(item,index) in option" :key="index" @keyup="liKey" @click="itemClick(item)" >{{item[label]}}</li> </ul> <div class="iconA" > <i v-if="bindValueLine" class="el-icon-circle-close" @click.prevent.stop="removeData"></i> <i v-if="!bindValueLine" class="el-icon-arrow-down"></i> </div> </div> </template> <script> import {mapGetters} from 'vuex' export default { props:{ placeholder:String, optionList:Array, label:String, values:String, number:String, english:String, bindValue:[String,Number], }, data() { return { chart: null, option:[], value:"", isShow:false, li:[], num:undefined, bindValueLine:"" } }, watch:{ bindValue(val){ this.bindValueLine=val; }, bindValueLine(val){ this.$emit("update:bindValue",val); if(val&&!this.value){ this.queryName(val); }else if(!val){ this.value="" } }, optionList:{ handler(newVal){ if(!this.value&&this.bindValue){ this.queryName(this.bindValue); } }, deep:true } }, created() { //默认值回显 if(this.bindValue){ this.queryName(this.bindValue); } addEventListener('mousedown',this.mousedown); }, beforeDestroy() { removeEventListener('mousedown',this.mousedown) }, methods: { //默认值回显 queryName(val){ this.optionList.map(item=>{ if(item[this.values]==val){ this.value=item[this.label] } }) }, //输入框获取焦点下拉框出现 inputFocus(){ this.isShow=true; this.option=this.optionList.filter((item,index)=>{ return index<30 }); this.$nextTick(()=>{ this.li=document.getElementsByClassName("selectItems"); }) }, //关闭按钮清除数据 removeData(){ this.value=""; this.num=undefined; this.bindValueLine=""; }, //鼠标失去焦点时关闭下拉框 mousedown(e){ if(e.path[1]&&e.path[1].id!="selfSelectA"&&e.path[1]&&e.path[2].id!="selfSelectA"){ this.isShow=false; if(!this.bindValueLine){ this.value=""; } }else if(!e.path[1]){ this.isShow=false; if(!this.bindValueLine){ this.value=""; } } }, //输入框绑定值发生变化时下拉框数据随之发生变化 valueInput(val){ let pattern = new RegExp("[\u4E00-\u9FA5]+"); //用第一个字符判断是中文字符还是英文字符或是数字,中文匹配正则表达式 if(pattern.test(this.value.split(",")[0]) && this.value.length > 0){ //中文 this.option=this.optionList.filter(item=>{ return item[this.label]&&item[this.label].indexOf(this.value)>-1 }) }else if(/^[0-9]+.?[0-9]*$/.test(this.value.split(",")[0]) && this.value.length > 0){ //数字 this.option=this.optionList.filter(item=>{ return item[this.number] && item[this.number].toString().indexOf(this.value)>-1 }) }else if(this.value.length > 0){ //英文 this.option=this.optionList.filter(item=>{ return item[this.english] && item[this.english].toUpperCase().indexOf(this.value.toUpperCase())>-1 }) }else if(!this.value){ //为空时清除绑定的数据 重置下拉框列表数据 this.bindValueLine=""; this.option=this.optionList.filter((item,index)=>{ return index<30 }) } this.$nextTick(()=>{ this.li=document.getElementsByClassName("selectItems"); this.num=undefined; }) }, //点击下拉框数据 选中值 itemClick(item){ this.value=item[this.label]; this.bindValueLine=item[this.values]; this.isShow=false; }, //输入框聚焦时按下箭头默认选中下拉框第一条数据 inputKey(e) { switch (e.keyCode) { case 40: if(!this.num){ this.num=0; } this.li[this.num].focus(); //下键 break; case 13: //回车 break; default: break } }, //下拉框列表键盘时间 上下移动 liKey(e){ switch (e.keyCode) { case 40: if(this.num>this.option.length-1){ this.num=0 }else{ this.num++ } this.li[this.num].focus(); //下键 break; case 38: if(this.num==0){ this.num=this.option.length-1 }else{ this.num-- } this.li[this.num].focus(); //上键 break; case 13: //回车 this.value=this.option[this.num][this.label]; this.bindValueLine=this.option[this.num][this.values]; this.isShow=false; break; default: break } } } } </script> <style scoped lang="scss"> .selfSelect{ margin:0 auto; width:100%; position: relative; input{ width: 100%; height: 30px; } .iconA{ width:10px; height: 20px; position: absolute; top:6px; right:10px; color: #606266; text-align: right; } ul{ list-style: none; margin:0; padding:0; width: 250px; height: 200px; overflow: auto; border:1px solid #999999; position: absolute; top:31px; left:0; z-index:1000; background-color: #ffffff; li{ width:100%; font-size: 14px; height: 25px; line-height: 25px; cursor: pointer; overflow: hidden; /*text-overflow: ellipsis;*/ border-bottom: 1px solid #999999; } li:hover{ background-color: #409EFF; color: #ffffff; } } .active{ background-color: #409EFF; color: #ffffff; } } </style>