uniapp uView picker组件多选封装改造

最近写项目遇到一个需求,手机端(uniapp H5)下拉选需要多选,用的是uView组件库,但是原有的picker组件并没有这个功能,索性自己上手了,简单封装一下。

1. 效果图

在这里插入图片描述
在这里插入图片描述

2. 使用方法
<template>
	<view>
		// 这里我用到的值就是 name 的拼接字符串 value,如果需要 code 集合,则需要调用 confirm方法 获取
		<g-picker v-model="value" :columns="columns" :filter="filter" @confirm="confirm">
		</g-picker>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				value: "",
				columns: [],
				filter: { label: 'dictLabel', value: 'dictValue' }
			}
		},
		methods: {
			confirm(data, value, label) {
				console.log(data, value, label)
			}
		}
	}
</script>
3. 使用说明
props:
  • value:picker组件绑定值,默认 name 用,拼接
  • columns: 数据源
  • filter:数据显示格式化,label 为组件显示名称 name字段(默认为label),value 为数据相对应的 code 字段(默认为value)
  • disabled:是否禁用
  • activedColor:选中后的颜色
  • inputAlign:文本对齐方式
  • placeholder:默认提示
Events:
  • confirm:点击确定按钮触发。(data, value, label) => {}
    • data:选中的数据集合
    • value:选中的数据 value 集合
    • label:选中的数据 label 集合
4. 源码
  1. 直接在 components 里面创建相同的文件夹和文件名,这样可以省去注册步骤直接引用。
    在这里插入图片描述
  2. g-picker.vue
<style lang="scss" scoped>
	.g-picker {

		.g-picker-value {
			display: flex;
		}

		.g-picker-con {
			color: #333;
			font-size: 28rpx;

			.g-picker-operate {
				display: flex;
				align-items: center;
				justify-content: space-between;
				height: 80rpx;
				padding: 0 32rpx;

				text {
					color: #999;

					&:last-child {
						color: #3c9cff;
					}
				}
			}

			.g-picker-list {
				min-height: 30vh;
				max-height: 60vh;
				overflow-y: scroll;

				.g-picker-item {
					position: relative;
					width: 100%;
					height: 80rpx;

					.g-picker-item_label {
						width: 66%;
						margin: 0 auto;
						text-align: center;
						line-height: 80rpx;
						white-space: nowrap;
						text-overflow: ellipsis;
						overflow: hidden;
					}

					.g-picker-item--actived {
						font-weight: 600;
					}

					.g-picker-item_icon {
						position: absolute;
						top: 50%;
						right: 40rpx;
						transform: translateY(-50%);
					}
				}
			}
		}
	}
</style>
<template>
	<view class="g-picker">
		<view class="g-picker-value" @click.native="showPicker">
			<u-input v-model="value" disabled disabledColor="#fff" :inputAlign="inputAlign" :placeholder="placeholder">
			</u-input>
			<u-icon v-if="!disabled" name="arrow-right" color="#c0c4cc"></u-icon>
		</view>
		<u-popup :show="show" :round="6" mode="bottom">
			<view class="g-picker-con">
				<view class="g-picker-operate">
					<text @click="show = false">取消</text>
					<text @click="confirm">确认</text>
				</view>
				<view class="g-picker-list">
					<view class="g-picker-item" v-for="(col, inx) in columnsList" :key="inx"
						@click="checkItem(col, inx)">
						<view :class="['g-picker-item_label', col._check ? 'g-picker-item--actived' : '']"
							:style="{color: col._check ? activedColor : '#333'}">{{ col[filter.label] }}</view>
						<u-icon class="g-picker-item_icon" v-show="col._check" name="checkbox-mark"
							:color="activedColor"></u-icon>
					</view>
				</view>
			</view>
		</u-popup>
	</view>
</template>

<script>
	export default {
		model: {
			prop: 'value',
			event: 'change'
		},
		props: {
			// picker组件绑定值,默认 name 用,拼接
			value: {
				type: String,
				default: ""
			},
			// 数据源
			columns: {
				type: Array,
				default: () => {
					return []
				}
			},
			// 数据显示格式化
			filter: {
				type: Object,
				default: () => {
					return {
						label: 'label',
						value: 'value'
					}
				}
			},
			// 是否禁用
			disabled: {
				type: Boolean,
				default: false
			},
			// 选中后颜色
			activedColor: {
				type: String,
				default: "#F58621"
			},
			// 文本对齐方式
			inputAlign: {
				type: String,
				default: "right"
			},
			// 默认提示
			placeholder: {
				type: String,
				default: "请选择"
			}
		},
		data() {
			return {
				show: false,
				columnsList: [],
				value_chx: []
			}
		},
		watch: {
			value: {
				handler(n) {
					if (n) this.reShow();
				},
				immediate: true
			},
			columns: {
				handler(n) {
					if (n.length) {
						this.columnsList = n
						for (let val of this.columnsList) {
							this.$set(val, '_check', false)
						}
					}
				},
				immediate: true
			}
		},
		methods: {
			showPicker() {
				if (this.disabled) return
				this.show = true
			},
			reShow() {
				let data = this.value.split(",")
				setTimeout(() => {
					for (let val of this.columnsList) {
						if (data.includes(val[this.filter.label])) val._check = true
					}
				}, 100)
			},
			checkItem(col, inx) {
				col._check = !col._check
			},
			// close() {
			// 	this.show = false
			// 	this.$emit("close")
			// },
			confirm() {
				let value = [],
					label = []
				this.value_chx = this.columns.filter(v => v._check)
				for (let val of this.value_chx) {
					value.push(val[this.filter.value])
					label.push(val[this.filter.label])
				}
				this.show = false
				this.$emit('confirm', this.value_chx, value, label)
				this.$emit('change', name.join(","))
			}
		}
	}
</script>

封装的比较简单,够我目前使用,大家可以根据自己的需求修改。

  • 15
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
要实现五级选择器,可以使用uView组件库中的Picker组件,并在其内部嵌套多个Picker组件。下面是一个五级选择器的示例代码: ```html <template> <view class="picker"> <picker :range="provinceList" @change="provinceChange"></picker> <picker :range="cityList" @change="cityChange"></picker> <picker :range="districtList" @change="districtChange"></picker> <picker :range="streetList" @change="streetChange"></picker> <picker :range="villageList" @change="villageChange"></picker> </view> </template> <script> export default { data() { return { provinceList: ['省份1', '省份2', '省份3'], cityList: ['城市1', '城市2', '城市3'], districtList: ['区县1', '区县2', '区县3'], streetList: ['街道1', '街道2', '街道3'], villageList: ['村庄1', '村庄2', '村庄3'] } }, methods: { provinceChange(e) { // 省份变化时更新城市列表 const index = e.detail.value this.cityList = this.getCityList(index) }, cityChange(e) { // 城市变化时更新区县列表 const index = e.detail.value this.districtList = this.getDistrictList(index) }, districtChange(e) { // 区县变化时更新街道列表 const index = e.detail.value this.streetList = this.getStreetList(index) }, streetChange(e) { // 街道变化时更新村庄列表 const index = e.detail.value this.villageList = this.getVillageList(index) }, villageChange(e) { // 村庄变化时输出最终结果 const index = e.detail.value const province = this.provinceList[index[0]] const city = this.cityList[index[1]] const district = this.districtList[index[2]] const street = this.streetList[index[3]] const village = this.villageList[index[4]] console.log(`${province}-${city}-${district}-${street}-${village}`) }, getCityList(provinceIndex) { // 根据省份获取城市列表 // TODO: 根据实际需求替换为异步请求或本地数据 return ['城市1', '城市2', '城市3'] }, getDistrictList(cityIndex) { // 根据城市获取区县列表 // TODO: 根据实际需求替换为异步请求或本地数据 return ['区县1', '区县2', '区县3'] }, getStreetList(districtIndex) { // 根据区县获取街道列表 // TODO: 根据实际需求替换为异步请求或本地数据 return ['街道1', '街道2', '街道3'] }, getVillageList(streetIndex) { // 根据街道获取村庄列表 // TODO: 根据实际需求替换为异步请求或本地数据 return ['村庄1', '村庄2', '村庄3'] } } } </script> <style> .picker { display: flex; flex-direction: row; justify-content: space-between; align-items: center; } </style> ``` 在上面的代码中,我们使用了五个Picker组件,分别对应省份、城市、区县、街道、村庄五个级别。每当用户选择某个级别的选项时,我们会根据该级别的值更新下一个级别的选项列表。当用户选择最后一个级别时,我们会输出最终的选择结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值