当前位置:网站首页>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单选、多选组件的完整代码。
边栏推荐
- 面试突击70:什么是粘包和半包?怎么解决?
- LTE时域、频域资源
- Software you should know as a programmer
- 我的驾照考试笔记(4)
- 第57章 业务逻辑之业务实体与数据库表的映射规则定义
- Greenplum数据库源码分析——Standby Master操作工具分析
- Little data on how to learn?Jida latest small learning data review, 26 PDF page covers the 269 - page document small data learning theory, method and application are expounded
- 57: Chapter 5: Develop admin management services: 10: Develop [get files from MongoDB's GridFS, interface]; (from GridFS, get the SOP of files) (Do not use MongoDB's service, you can exclude its autom
- 内网穿透 lanproxy部署
- 【luogu P1912】诗人小G(二分栈)(决策单调性优化DP)
猜你喜欢

研究生新同学,牛人看英文文献的经验,值得你收藏

数字孪生北京故宫,元宇宙推进旅游业进程

【无标题】

Acrel-5010重点用能单位能耗在线监测系统在湖南三立集团的应用
![[Energy Conservation Institute] Ankerui Food and Beverage Fume Monitoring Cloud Platform Helps Fight Air Pollution](/img/ca/e67c8e2196adb5a078acc44ba5ad6f.jpg)
[Energy Conservation Institute] Ankerui Food and Beverage Fume Monitoring Cloud Platform Helps Fight Air Pollution

Convolutional Neural Network (CNN) mnist Digit Recognition - Tensorflow

How PROE/Croe edits a completed sketch and brings it back to sketching state

Use WeChat official account to send information to designated WeChat users

使用微信公众号给指定微信用户发送信息

【Social Media Marketing】How to know if your WhatsApp is blocked?
随机推荐
LabVIEW 使用VISA Close真的关闭COM口了吗
Win10, the middle mouse button cannot zoom in and out in proe/creo
有用的网站
【kali-信息收集】(1.3)探测网络范围:DMitry(域名查询工具)、Scapy(跟踪路由工具)
Convolutional Neural Network (CNN) mnist Digit Recognition - Tensorflow
Debug一个ECC的ODP数据源
专利检索常用的网站有哪些?
自定义指令,获取焦点
外骨骼机器人(七):标准步态数据库
WhatsApp group sending actual combat sharing - WhatsApp Business API account
通配符 SSL/TLS 证书
[Multi-task optimization] DWA, DTP, Gradnorm (CVPR 2019, ECCV 2018, ICML 2018)
Zheng Xiangling, Chairman of Tide Pharmaceuticals, won the "2022 Outstanding Influential Entrepreneur Award" Tide Pharmaceuticals won the "Corporate Social Responsibility Model Award"
【Untitled】
如何写一个vim插件?
Custom command to get focus
C语言实现-直接插入排序(带图详解)
启明云端分享|盘点ESP8684开发板有哪些功能
为什么限制了Oracle的SGA和PGA,OS仍然会用到SWAP?
【节能学院】数据机房中智能小母线与列头柜方案的对比分析