当前位置:网站首页>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单选、多选组件的完整代码。
边栏推荐
- 【多任务模型】Progressive Layered Extraction: A Novel Multi-Task Learning Model for Personalized(RecSys‘20)
- 】 【 nn. The Parameter () to generate and why do you want to initialize
- Interview assault 70: what is the glue bag and a bag?How to solve?
- 实用新型专利和发明专利的区别?秒懂!
- Redis does check-in statistics
- [Multi-task learning] Modeling Task Relationships in Multi-task Learning with Multi-gate Mixture-of-Experts KDD18
- Hangao data import
- 互联网大厂研发流程
- 【Untitled】
- 使用微信公众号给指定微信用户发送信息
猜你喜欢
Use WeChat official account to send information to designated WeChat users
58:第五章:开发admin管理服务:11:开发【管理员人脸登录,接口】;(未实测)(使用了阿里AI人脸识别)(演示了,使用RestTemplate实现接口调用接口;)
Creo5.0 rough hexagon is how to draw
【节能学院】安科瑞餐饮油烟监测云平台助力大气污染攻坚战
我的驾照考试笔记(2)
【节能学院】智能操控装置在高压开关柜的应用
数字孪生北京故宫,元宇宙推进旅游业进程
【节能学院】推进农业水价综合改革的意见解读
【kali-信息收集】(1.4)识别活跃的主机/查看打开的端口:Nmap(网络映射器工具)
Acrel-5010重点用能单位能耗在线监测系统在湖南三立集团的应用
随机推荐
我的驾照考试笔记(3)
[Multi-task optimization] DWA, DTP, Gradnorm (CVPR 2019, ECCV 2018, ICML 2018)
虚拟机的IP地址自动变为127.0.0.1
Use WeChat official account to send information to designated WeChat users
17、负载均衡
[Personal work] Wireless network image transmission module
大整数相加,相减,相乘,大整数与普通整数的相乘,相除
myid file is missing
部署zabbix
SIPp installation and use
【七夕特别篇】七夕已至,让爱闪耀
LabVIEW 使用VISA Close真的关闭COM口了吗
Redis 做网页UV统计
通配符 SSL/TLS 证书
Zheng Xiangling, Chairman of Tide Pharmaceuticals, won the "2022 Outstanding Influential Entrepreneur Award" Tide Pharmaceuticals won the "Corporate Social Responsibility Model Award"
环境变量,进程地址空间
The Internet giant development process
18、分布式配置中心nacos
Failed to re-init queues : Illegal queue capacity setting (abs-capacity=0.6) > (abs-maximum-capacity
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