当前位置:网站首页>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单选、多选组件的完整代码。
边栏推荐
- An implementation of an ordered doubly linked list.
- SIPp 安装及使用
- 【Untitled】
- 58:第五章:开发admin管理服务:11:开发【管理员人脸登录,接口】;(未实测)(使用了阿里AI人脸识别)(演示了,使用RestTemplate实现接口调用接口;)
- myid file is missing
- 作为程序员你应该会的软件
- Win10, the middle mouse button cannot zoom in and out in proe/creo
- 漏刻有时文档系统之XE培训系统二次开发配置手册
- regular expression
- Failed to re-init queues : Illegal queue capacity setting (abs-capacity=0.6) > (abs-maximum-capacity
猜你喜欢
17、负载均衡
Win10, the middle mouse button cannot zoom in and out in proe/creo
WhatsApp group sending actual combat sharing - WhatsApp Business API account
Greenplum Database Source Code Analysis - Analysis of Standby Master Operation Tools
Buttons with good user experience should not have hover state on mobile phones
[Energy Conservation Institute] Ankerui Food and Beverage Fume Monitoring Cloud Platform Helps Fight Air Pollution
Interview assault 70: what is the glue bag and a bag?How to solve?
【无标题】
专利检索常用的网站有哪些?
Get started quickly with MongoDB
随机推荐
【Untitled】
【Untitled】
30天刷题计划(五)
【kali-信息收集】(1.4)识别活跃的主机/查看打开的端口:Nmap(网络映射器工具)
【torch】张量乘法:matmul,einsum
Custom command to get focus
如何写一个vim插件?
有用的网站
Use WeChat official account to send information to designated WeChat users
Greenplum Database Source Code Analysis - Analysis of Standby Master Operation Tools
Multithreaded producers and consumers
第55章 业务逻辑之订单、支付实体定义
算法---解码方法(Kotlin)
The Internet giant development process
智能硬件开发怎么做?机智云全套自助式开发工具助力高效开发
大神经验:软件测试的自我发展规划
[Energy Conservation Institute] Comparative analysis of smart small busbar and column head cabinet solutions in data room
【多任务学习】Modeling Task Relationships in Multi-task Learning with Multi-gate Mixture-of-Experts KDD18
启明云端分享|盘点ESP8684开发板有哪些功能
使用Huggingface在矩池云快速加载预训练模型和数据集