<template> <view class="main"> <view class="input" :style="disabled?'background-color:#f5f7fa':''"> <input @click="showModal" v-model="_value" :style="disabled?'color:#c0c4cc':''" :placeholder="placeholder" disabled/> <text v-if="clearable&&!disabled" @click="empty" class="selectIcon iconcross"></text> </view> <view class="select-modal" :class="isShowModal?'show':''" @tap="hideModal"> <view class="select-dialog" @tap.stop="" :style="{backgroundColor:bgColor}"> <view class="select-bar bg-white"> <view class="action text-blue" @tap="cancelClick">{{cancelText}}</view> <view class="action text-green" @tap="confirmClick">{{confirmText}}</view> </view> <view class="select-content"> <view class="select-item" v-for="(item,index) in list" :key="index" :style="valueIndexOf(item)?'color:'+selectColor+';background-color:'+selectBgColor+';':'color:'+color+';'" @click="select(item)"> <view class="title">{{getLabelKeyValue(item)}}</view> <text class="selectIcon icongou" v-if="valueIndexOf(item)"></text> </view> </view> </view> </view> </view> </template> <script> export default { data() { return { isShowModal:false }; }, props: { value:{ type:[Number,String,Array,Object], default:null }, placeholder:{ // 占位符 default: "", type: String }, multiple:{ // 是否多选 default: false, type: Boolean }, list: { default: () => [], type: Array }, valueKey:{ // 指定list中valueKey的值作为下拉框绑定内容 default: 'value', type: String }, labelKey:{ // 指定list中labelKey的值作为下拉框显示内容 default: 'label', type: String }, disabled: { default: false, type: Boolean }, clearable:{ default: false, type: Boolean }, cancelText:{ default: "取消", type: String }, confirmText:{ default: "确定", type: String }, color:{ default: "#000000", type: String }, selectColor:{ default: "#0081ff", type: String }, bgColor:{ default: "#F1F1F1", type: String }, selectBgColor:{ default: "#FFFFFF", type: String } }, computed: { _value: { get() { return this.get_value(this.value); }, set(val) { this.$emit('change', val); } } }, created() { }, methods: { get_value(val){ // 将数组值转换为以,隔开的字符串 if(val || val===0){ if(Array.isArray(val)){ let chooseAttr = [] val.forEach(item=>{ let choose = this.list.find(temp => { let val_val = this.getValueKeyValue(temp) return item === val_val }) chooseAttr.push(choose) }) let values = chooseAttr.map(temp => this.getLabelKeyValue(temp)).join(',') return values } else { let choose = this.list.find(temp => { let val_val = this.getValueKeyValue(temp) return val === val_val }) return this.getLabelKeyValue(choose) } } else { return "" } }, select(item){ // 点击选项 let val = this.getValueKeyValue(item); if(this.multiple){ let _value = this.value; let index = _value.indexOf(val); if(index!=-1){ _value.splice(index,1) this.$emit('change', _value) } else { _value.push(val) this.$emit('change', _value) } } else { this.$emit('change', val) this.hideModal() } }, valueIndexOf(item){ let val = this.getValueKeyValue(item); if(Array.isArray(this.value)){ return this.value.indexOf(val)!=-1 } else { return this.value === val } }, getLabelKeyValue(item){ // 获取label return item[this.labelKey] }, getValueKeyValue(item){ // 获取value return item[this.valueKey] }, empty(){ // 清空 if(this.multiple){ this.$emit('change', []) } else { this.$emit('change', '') } }, cancelClick(){ // 点击取消 this.$emit('cancel', this._value) this.hideModal() }, confirmClick(){ // 点击确定 this.$emit('confirm', this._value) this.hideModal() }, showModal(){ // 显示model if(!this.disabled){ this.isShowModal = true } }, hideModal(){ // 隐藏model this.isShowModal = false } } } </script> <style> @font-face {font-family: "selectIcon"; src: url('//at.alicdn.com/t/font_1833441_ycfzdhg2u3.eot?t=1590375117208'); /* IE9 */ src: url('//at.alicdn.com/t/font_1833441_ycfzdhg2u3.eot?t=1590375117208#iefix') format('embedded-opentype'), /* IE6-IE8 */ url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAMEAAsAAAAABvQAAAK4AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDBgqBRIFCATYCJAMMCwgABCAFhQUHNRsfBsg+QCa3uoO0oAJTMwhxVu965keqWBy1hkbwtfzWb2Z279/shRhJisKF6FApKLI7oyBbpAaHo3w24k+ca9EUJbDmjaeznUdZ/FOUlkWdJ33rizZY/Pw6J5Xw0qKYxHTMesePHVT6EFpaC4zV70sKi2bYgNPc1w0WHnDVC/e/UnNTgyP+4Jq6BBpIHoisgypLaIAFEtU0wgeaIG8Yu4nAIZwnUK1QgFfOT6nUUoBpgXjj2lqplTMpiuXtCW3N2iK+aPTS2/Qdnzny8d+5IEiaDMy99exklra//FrKnX48pChmgrq5QcYRQCEe17ruqgqLAKv8WntwqwhpLms/nB5yW/iHRxJEC0QOgT3NnfgF01NBKvOuIzNoZdh5gJuAeGrsozE8vOJ7u5D832oz55039W5G+S52K0H+zNf1TJz07k26kqoQybRfwVFV4rjDS/K8EXUyuF1cXnT3weKS9Rvdm/xe7h8oA1hLwOR18R+Y4n4zwpr4z5SU089Vc+cpfWL+mn5APmT3Z39jeOs/GbWjK+DnmsuL/u6ehMX4j4yedSVkAUUuPh3TY022MtKZUEOtPqCb8Bkvnr5XT6imU0gGrEJW7aAL/gw0OhegVV2F6pC7uTOppirKIA4MFQhTrpCM+AbZlDu64L/QmAkQWlMhQXU75D07O9Gtl0PUYjTBLyAzOLNQYtypIEEjvsXtBLQTooV2nrQrGEau2gKmZlR4L8gwnGtBJbUn1diCOOQUnEkTkRAOeci9KHOQxvFro+tx3ZcGAaeljstCSBNDJuArgIyBYyy6OdZxAhHIELu1IC9AtgShCVtLltEKrSff1XoHJo3RC33hM63o3j6pSNkmqmIWEAtxFHB2OwoRBAfyeqE3r2ogHeF42dBhs7gvf7CukH5MmlUGOCpHihxFfs6TehDyKCqVAA==') format('woff2'), url('//at.alicdn.com/t/font_1833441_ycfzdhg2u3.woff?t=1590375117208') format('woff'), url('//at.alicdn.com/t/font_1833441_ycfzdhg2u3.ttf?t=1590375117208') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ url('//at.alicdn.com/t/font_1833441_ycfzdhg2u3.svg?t=1590375117208#selectIcon') format('svg'); /* iOS 4.1- */ } .selectIcon { font-family: "selectIcon" !important; font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .icongou:before { content: "\e61c"; } .iconcross:before { content: "\e61a"; } </style> <style lang="scss" scoped> .main{ font-size: 28rpx; } .bg-white{ background-color: #FFFFFF; } .text-blue{ color: #0081ff; } .text-green{ color: #39b54a; } .input { display: flex; align-items:center; font-size: 28rpx; height: 60rpx; padding: 10rpx 20rpx; border-radius: 10rpx; border-style: solid; border-width: 1rpx; border-color: rgba(0, 0, 0, 0.1); input{ flex: 1; } } .select-modal { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 9999; opacity: 0; outline: 0; text-align: center; -ms-transform: scale(1.185); transform: scale(1.185); backface-visibility: hidden; perspective: 2000rpx; background: rgba(0, 0, 0, 0.6); transition: all 0.3s ease-in-out 0s; pointer-events: none; margin-bottom: -1000rpx; &::before { content: "\200B"; display: inline-block; height: 100%; vertical-align: bottom; } .select-dialog { position: relative; display: inline-block; margin-left: auto; margin-right: auto; background-color: #f8f8f8; overflow: hidden; width: 100%; border-radius: 0; .select-content{ // background-color: #F1F1F1; max-height: 420rpx; overflow:auto; .select-item{ padding: 20rpx; display: flex; .title{ flex: 1; } } } } } .select-modal.show { opacity: 1; transition-duration: 0.3s; -ms-transform: scale(1); transform: scale(1); overflow-x: hidden; overflow-y: auto; pointer-events: auto; margin-bottom: 0; } .select-bar { padding: 0 20rpx; display: flex; position: relative; align-items: center; min-height: 80rpx; justify-content: space-between; .action { display: flex; align-items: center; height: 100%; justify-content: center; max-width: 100%; } } </style>