工作中,开发使用的移动端UI库是VUX。但是VUX的选择控件selector在手机上呈现了类原生样式,如图一,实在不太美观。并且选项太多时无法达到渐进匹配的功能。
因此,决定在VUX的基础上用x-input和x-dialog封装一个类似选择器的控件,实现弹框选择,输入渐进匹配更能,并且在样式上看起来更美观些。效果如图二。

该组件是在VUX上封装的,您的项目首先需要使用VUX依赖
自定义组件
mySelectDialog
<template>
<div >
<div >
<div class="div_box" @click="showDialog">
<template v-if=" label ">
<span >{{ label }}</span>
<span style="float: right;height:30px;"><x-icon style="margin-top: 5px;" type="ios-arrow-forward" size="20"></x-icon></span>
</template>
<template v-else>
<span class="placeholder">{{ placeholder }}</span>
<span style="float: right;height:30px;"><x-icon style="margin-top: 5px;" type="ios-arrow-forward" size="20"></x-icon></span>
</template>
</div>
</div>
<div v-transfer-dom>
<x-dialog v-model="dialogVisible">
<div class="dialog_header">
<span style="float:left;"> {{ placeholder }}</span>
<span style="float: right;"><icon name="close" scale="4" @click.native="onclickClose"></icon></span>
</div>
<div style="background-color: #F0F0F0;margin: 10px;">
<x-input placeholder="请输入搜索内容" v-model="queryValue" @on-change="queryValueChange"></x-input>
</div>
<div style="height: calc(50vh);overflow: auto;">
<ul>
<li v-for="(item,index) in liData" style="padding: 5px;border: 1px solid #F0F0F0;" @click="onClick_li(item)">{{ item[valueMap[1]] }}</li>
</ul>
</div>
</x-dialog>
</div>
</div>
</template>
import { XInput, XButton,TransferDomDirective as TransferDom, XDialog } from 'vux'
export default {
props:{
value:[String,Number,Object],
data:Array,
valueMap:{
type:Array,
default:() => ['key','label']
},
placeholder:{
type:String,
default:'请选择'
},
},
directives: { TransferDom },
components: { XInput, XButton, XDialog },
data() {
return {
liData:[],
queryValue:'',
dialogVisible:false
}
},
mounted: function() { //生命周期
this.liData = this.data.slice(0);
},
computed: { //计算属性
label(){
if( typeof this.value === 'object' ){
return this.value[this.valueMap[1]];
}else{
let label = '';
for( let i = 0; i < this.data.length; i++ ){
if( this.value == this.data[i][this.valueMap[0]] ) label = this.data[i][this.valueMap[1]];
}
return label;
}
}
},
methods: { //函数
showDialog:function(){
this.dialogVisible = true;
},
onclickClose:function(){
this.queryValue = '';
this.dialogVisible = false;
},
onClick_li:function(val){
this.queryValue = '';
this.dialogVisible = false;
if( typeof this.value === 'object' ){
this.$emit('input', val);
}else{
this.$emit('input', val[this.valueMap[0]]);
}
},
queryValueChange:function(){
this.liData = [];
for( let i = 0; i < this.data.length; i++){
if( this.data[i][this.valueMap[1]].indexOf( this.queryValue ) > -1 ){
this.liData.push( this.data[i] );
}
}
},
},
created: function() {
},
watch: {
data:function(nval,oval){
this.liData = nval.slice(0);
},
value:function (nval,oval) {
this.$emit('change', nval);
}
}
}
.div_box{
background-color: #F0F0F0;
width: 100%;
height:50px;
line-height: 30px;
padding: 10px 15px;
box-sizing: border-box;
}
.placeholder{
color: #a9a9a9;
}
.dialog_header{
height: 40px;
background-color: #d81e06;
line-height: 40px;
color: #fff;
}
属性
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| value / v-model | 绑定值 | string / number / object | -- |
| data | 选择列表 | Array | -- |
| valueMap | 设置键值对映射用以自动转换接口数据, 如 ['key', 'label'] | Array | ['key','label'] |
| placeholder | 占位符 | string | 请选择 |
事件
| 事件 | 说明 | 回调参数 |
|---|---|---|
| change | 选中值发生变化时触发 | 目前的选中值 |
补充
组件的data属性,选择列表的数组目前只支持元素为{"key":1,"label":"test"}类型的对象数组,暂不支持基础数据类型的数组,如["张三","李四","王五"]
应用
v-model绑定的属性是string类型时,选择后的值为选择列表映射对象的key,而不是label。
<template>
<div>
<my-select-dialog v-model="department" :data="departmentData" placeholder="请选择部门" @change="onChange"></my-select-dialog>
</div>
</template>
<script>
import mySelectDialog from './components/mySelectDialog.vue';
export default {
components: { mySelectDialog },
data() {
return {
department:'',
departmentData:[
{
"key":1,
"label":"电脑部"
},
{
"key":2,
"label":"设计部"
},
{
"key":3,
"label":"生产部"
}
],
}
},
methods: { //函数
onChange:function(val){
console.log(val);
}
}
}
</script>
设置键值对映射:
<template>
<div>
<my-select-dialog v-model="user" :value-map="['user_key','user_name']" :data="userData" placeholder="请选择用户" @change="onChange"></my-select-dialog>
</div>
</template>
<script>
import mySelectDialog from './components/mySelectDialog.vue';
export default {
components: { mySelectDialog },
data() {
return {
user:{},
userData:[
{
"user_key":1,
"user_name":"管理员"
},
{
"user_key":2,
"user_name":"张三"
},
{
"user_key":3,
"user_name":"李四"
}
],
}
},
methods: { //函数
onChange:function(val){
console.log(val);
},
}
}
</script>