当前位置:网站首页>vant实现Select效果--单选和多选
vant实现Select效果--单选和多选
2022-08-01 20:22:00 【谈谈的心情】
vue项目无论是用element中的Select选择器,还是使用公司维护的组件,都可以轻松实现单选和多选的需求,但在移动端使用vant时,找了几遍发现居然没有提供Select组件,下面提供对单选和多选组件的封装。
单选效果:

多选效果:
1、封装单选组件(VanFieldSelectPicker)
<template>
<div class="dh-field">
<div class=" van-hairline--bottom">
<van-field
v-model="resultLabel"
v-bind="$attrs"
readonly
:is-link="$attrs.disabled === undefined"
input-align="right"
error-message-align='right'
class="dh-cell"
@click="showPopu($attrs.disabled)"
/>
<van-popup v-model="show" position="bottom">
<van-field v-if="isSearch" v-model="searchVal" input-align="left" placeholder="搜索" @input="search"/>
<van-picker
v-bind="$attrs"
:columns="columnsData"
show-toolbar
@cancel="cancel"
@confirm="onConfirm"
@change="change"
:value-key="this.option.label"
/>
</van-popup>
</div>
</div>
</template>
<script>
export default {
name: 'VanFieldSelectPicker',
model: {
prop: 'selectValue'
},
props: {
columns: {
type: Array,
default: function () {
return []
}
},
selectValue: {
type: [String, Number],
default: ''
},
option: {
type: Object,
default: function () {
return { label: 'label', value: 'value' }
}
},
isSearch: {
type: Boolean,
default: false
},
offOption: { // 关闭option配置key-value;当数据是非集合的数组的时候,开启
type: Boolean,
default: false
}
},
computed: {
resultLabel: {
get () {
const res = this.columns.filter(item => {
const data = this.offOption ? item : item[this.option.value]
return data === this.resultValue
})
let label = ''
if (res.length) {
label = this.offOption ? res[0] : res[0][this.option.label]
}
return label
},
set () {
}
}
},
data () {
return {
show: false,
searchVal: '',
resultValue: this.selectValue,
columnsData: []
}
},
methods: {
search (val) {
if (val) {
this.columnsData = this.columnsData.filter(item => {
const data = this.offOption ? item : item[this.option.label]
return data.indexOf(val) > -1
})
} else {
this.columnsData = JSON.parse(JSON.stringify(this.columns))
}
},
onConfirm (value, index) {
const data = this.offOption ? value : value[this.option.value]
this.resultValue = data
this.show = !this.show
this.$emit('confirm', value, index, this.resultValue)
},
change (val, index) {
this.$emit('change', val, index, this.resultValue)
},
cancel (val, index) {
this.show = !this.show
this.$emit('cancel', val, index, this.resultValue)
},
showPopu (disabled) {
this.columnsData = JSON.parse(JSON.stringify(this.columns))
this.resultValue = this.selectValue
if (disabled !== undefined && disabled !== false) {
return false
} else {
this.show = !this.show
}
}
},
watch: {
selectValue: function (newVal) {
this.resultValue = newVal
},
resultValue (val) {
this.searchVal = ''
this.columnsData = JSON.parse(JSON.stringify(this.columns))
this.$emit('input', val)
}
}
}
</script>
<style lang="scss" scoped>
.dh-field {
padding: 0;
background:#fff;
.dh-cell.van-cell {
padding: 10px 0;
}
.dh-cell.van-cell--required::before {
left: -8px;
}
.van-popup {
border-radius: 20px 20px 0 0;
}
}
</style>1.1 单选组件的使用
①使用到该组件的页面导入单选组件
② 在单选地方使用

<van-field-select-picker
v-model="orderType"
placeholder="请选择"
:columns="orderClassify"
:option="{label:'configName', value:'configCode'}"
@confirm="onOrderClassify"
/>③orderClassify是后台返回的数据,{label:'configName', value:'configCode'} 对应选项的key-value,可以参考下面后台返回的数据

④单选事件 onOrderClassify 对应的方法
onOrderClassify(data1, index, data2) {
// data1 当前这一条的obj数据
// index 当前选择的索引
// data2 当前这一条数据的value
this.orderName = data1.configName
},上面便是单选弹框的完整代码,下面开始多选组件的封装
2、封装多选组件(VanFieldCheckbox)
<template>
<div class="dh-field">
<div class="van-hairline--bottom">
<van-field
v-model="resultLabel"
v-bind="$attrs"
readonly
:is-link="$attrs.disabled === undefined"
error-message-align='right'
input-align="right"
class="dh-cell"
@click="showPopu($attrs.disabled)"
/>
<van-popup v-model="show" position="bottom" class="" >
<div class="van-picker__toolbar">
<button type="button" class="van-picker__cancel" @click="cancel">取消</button>
<div class="van-ellipsis van-picker__title">{
{$attrs.label}}</div>
<button type="button" class="van-picker__confirm" @click="onConfirm">确认</button>
</div>
<div style="max-height:264px; overflow-y:auto;">
<van-field v-if="isSearch" v-model="searchVal" input-align="left" placeholder="搜索" @input="search"/>
<van-cell title="全选">
<template #right-icon>
<van-checkbox v-model="checkedAll" name="all" @click="toggleAll"/>
</template>
</van-cell>
<van-checkbox-group ref="checkboxGroup" v-model="checkboxValue" @change="change">
<van-cell-group>
<van-cell
v-for="(item, index) in columnsData"
:key="item[option.value]"
:title="item[option.label]"
clickable
@click="toggle(index)"
>
<template #right-icon>
<van-checkbox ref="checkboxes" :name="item[option.value]" />
</template>
</van-cell>
</van-cell-group>
</van-checkbox-group>
</div>
</van-popup>
</div>
</div>
</template>
<script>
export default {
name: 'VanFieldCheckbox',
model: {
prop: 'selectValue'
},
props: {
columns: {
type: Array,
default: function () {
return []
}
},
selectValue: {
type: Array,
default: function () {
return []
}
},
option: {
type: Object,
default: function () {
return { label: 'label', value: 'value' }
}
},
// 是否支持搜索
isSearch: {
type: Boolean,
default: true
}
},
computed: {
resultLabel: {
get () {
const res = this.columns.filter(item => {
return this.resultValue.indexOf(item[this.option.value]) > -1
})
const resLabel = res.map(item => {
return item[this.option.label]
})
return resLabel.join(',')
},
set () {
}
}
},
data () {
return {
show: false,
searchVal: '',
columnsData: JSON.parse(JSON.stringify(this.columns)),
checkboxValue: JSON.parse(JSON.stringify(this.selectValue)),
checkedAll: false,
resultValue: JSON.parse(JSON.stringify(this.selectValue))
}
},
methods: {
// 搜索
search (val) {
if (val) {
this.columnsData = this.columnsData.filter(item => {
return item[this.option.label].indexOf(val) > -1
})
} else {
this.columnsData = JSON.parse(JSON.stringify(this.columns))
}
},
getData (val) {
const res = this.columnsData.filter(item => {
return val.indexOf(item[this.option.value]) > -1
})
return res
},
onConfirm () {
this.resultValue = this.checkboxValue
this.show = !this.show
this.$emit('confirm', this.resultValue, this.getData(this.resultValue))
},
change (val) {
this.$emit('change', val, this.getData(this.resultValue))
},
cancel () {
this.show = !this.show
this.$emit('cancel', this.resultValue)
},
toggle (index) {
this.$refs.checkboxes[index].toggle()
},
toggleAll (all) {
this.$refs.checkboxGroup.toggleAll(this.checkedAll)
},
showPopu (disabled) {
this.columnsData = JSON.parse(JSON.stringify(this.columns))
this.checkboxValue = JSON.parse(JSON.stringify(this.selectValue))
this.resultValue = JSON.parse(JSON.stringify(this.selectValue))
if (disabled !== undefined && disabled !== false) {
return false
} else {
this.show = !this.show
}
}
},
watch: {
selectValue: function (newVal) {
this.resultValue = newVal
},
resultValue (val) {
this.searchVal = ''
this.columnsData = JSON.parse(JSON.stringify(this.columns))
this.$emit('input', val)
},
columnsData: {
handler (val) {
if (val.length && val.length === this.checkboxValue.length) {
this.checkedAll = true
} else {
this.checkedAll = false
}
},
immediate: true
},
checkboxValue: {
handler (val) {
if (val.length && val.length === this.columnsData.length) {
this.checkedAll = true
} else {
this.checkedAll = false
}
},
immediate: true
}
}
}
</script>
<style lang="scss" scoped>
.dh-field {
padding: 0;
background:#fff;
.dh-cell.van-cell {
padding: 10px 0;
}
.dh-cell.van-cell--required::before {
left: -8px;
}
.van-popup {
border-radius: 20px 20px 0 0;
}
}
</style>①使用到该组件的页面导入多选组件,和单选组件的导入一致,参考上面
② 在多选地方使用

<van-field-checkbox
v-model="checkedExecutors"
placeholder="请选择"
:columns="executor"
label-width="100"
:option="{label:'name', value:'userId'}"
/>③executor是后台返回的数据,{label:'name', value:'userId'}对应选项的key-value,可以参考下面后台返回的数据

④多选事件上面我没用到,我是直接v-model绑定了选中的数据,如果需要在事件中额外处理数据,可以通过@confirm="onConfirm" 来绑定事件(正常获取值用不到,直接v-model即可)
onConfirm (data1, data2) {
// data1 是当前选中数据的value的数组
// data2 是当前选中数据的整个obj集合
},以上便是基于popup和cell、field封装的select单选、多选组件的完整代码。
边栏推荐
- 互联网大厂研发流程
- 18. Distributed configuration center nacos
- 通配符 SSL/TLS 证书
- 图文详述Eureka的缓存机制/三级缓存
- 【节能学院】智能操控装置在高压开关柜的应用
- Failed to re-init queues : Illegal queue capacity setting (abs-capacity=0.6) > (abs-maximum-capacity
- To promote energy conservation institute 】 【 the opinions of the agricultural water price reform
- 用户体验好的Button,在手机上不应该有Hover态
- Wildcard SSL/TLS certificate
- 【节能学院】安科瑞餐饮油烟监测云平台助力大气污染攻坚战
猜你喜欢
随机推荐
New graduate students, great experience in reading English literature, worthy of your collection
9月备考PMP,应该从哪里备考?
Wildcard SSL/TLS certificate
Interview assault 70: what is the glue bag and a bag?How to solve?
Digital twin Beijing the imperial palace, yuan universe is the process of tourism
XSS range intermediate bypass
Redis 做签到统计
卷积神经网络(CNN)mnist数字识别-Tensorflow
【Social Media Marketing】How to know if your WhatsApp is blocked?
Redis does web page UV statistics
LabVIEW 使用VISA Close真的关闭COM口了吗
[Energy Conservation Institute] Ankerui Food and Beverage Fume Monitoring Cloud Platform Helps Fight Air Pollution
Creo5.0 rough hexagon is how to draw
第58章 结构、纪录与类
To promote energy conservation institute 】 【 the opinions of the agricultural water price reform
第60章 ApplicationPart自动集成整体性和独立性插件项
【nn.Parameter()】生成和为什么要初始化
泰德制药董事长郑翔玲荣膺“2022卓越影响力企业家奖” 泰德制药荣获“企业社会责任典范奖”
因斯布鲁克大学团队量子计算硬件突破了二进制
作为程序员你应该会的软件









