uniapp 自定义picker

2,123 阅读1分钟
// 单选 pickerList:[{label:'全部',value:0}]
<ns-picker ref="type" :pickerList="balanceType" @onConfirm="typeChange"></ns-picker>
// 时间
<ns-picker ref="date" mode="date" @onConfirm="dateChange"></ns-picker>
// 多选 pickerList:[["北京市"],["北京市"],["东城区"]] multiIndex传入当前的地址索引
<ns-picker ref="logistics" mode="multiSelector" :value="multiIndex" :pickerList="multiArray"
        @onConfirm="handleValueChange" @columnChange="handleColumnChange"></ns-picker>
        
async handleColumnChange(e) {
    let col = e.column;  // 第几列
    let row = e.value;   // 选中的索引
    this.multiIndex[col] = row;
    switch (col) {
        case 0:
            //选择省,加载市、区县
            ...
            break;
        case 1:
            //选择市,加载区县
           ...
        case 2:
            ...
            break;
    }
},

以下为my-picker内容

<template>
    <view>
        <view class="picker-modal" v-if="showPicker"></view>
        <view class="picker-content" :style="{ transform: showPicker ? 'translateY(0)' : 'translateY(100%)' }">
            <view class="picker-header flex-justify">
                <view class="text-default" @click="cancel">取消</view>
                <view class="title">{{ title }}</view>
                <view class="confirm" @click="confirm">确定</view>
            </view>
            <picker-view indicator-style="height: 90rpx;" class="picker-view" :value="pickerValue"
                @change="changePicker" @pickstart="pickstart" @pickend="pickend" v-if="'selector' === mode">
                <picker-view-column>
                    <view class="picker-item" :class="pickerValue[0] === index ? 'font-bold' : ''"
                        v-for="(item, index) in pickerList" :key="index">
                        {{ item.label }}
                    </view>
                </picker-view-column>
            </picker-view>
            <picker-view indicator-style="height: 90rpx;" class="picker-view" :value="pickerValue"
                @change="changePicker" @pickstart="pickstart" @pickend="pickend" v-if="'date' === mode">
                <picker-view-column>
                    <view class="picker-item" v-for="(item, index) in years" :key="index">{{ item }}年</view>
                </picker-view-column>
                <picker-view-column>
                    <view class="picker-item" v-for="(item, index) in months" :key="index">{{ item }}月</view>
                </picker-view-column>
                <picker-view-column v-if="'days' === fields">
                    <view class="picker-item" v-for="(item, index) in months" :key="index">{{ item }}月</view>
                </picker-view-column>
            </picker-view>
            <picker-view indicator-style="height: 90rpx;" class="picker-view" :value="pickerValue"
                @change="changePicker" @pickstart="pickstart" @pickend="pickend" v-if="'multiSelector' === mode">
                <picker-view-column v-for="(list,index) in pickerList" :key="index">
                    <view class="picker-item" :class="pickerValue[index] === index1 ? 'font-bold' : ''"
                        v-for="(item, index1) in list" :key="index1">{{ item }}</view>
                </picker-view-column>
            </picker-view>
        </view>
    </view>
</template>

<script>
    export default {
        props: {
            title: {
                type: String,
                default: ''
            },
            pickerList: {
                type: Array
            },
            mode: {
                type: String,
                default: 'selector'
            },
            fields: {
                type: String,
                default: 'month'
            },
            value: {
                type: Array
            }
        },
        watch: {
            pickerList() {}
        },
        data() {
            const date = new Date();
            const years = [];
            const year = date.getFullYear();
            const months = [];
            const month = date.getMonth() + 1;
            const days = [];
            const day = date.getDate();
            for (let i = 1990; i <= date.getFullYear(); i++) {
                years.push(i);
            }
            for (let i = 1; i <= 12; i++) {
                months.push(i);
            }
            for (let i = 1; i <= 31; i++) {
                days.push(i);
            }
            const pickerValue = 'multiSelector' === this.mode ? this.value : ('date' === this.mode ? [9999, month - 1,
                day - 1
            ] : [0]);
            return {
                days: days,
                years: years,
                months: months,
                pickerValue: pickerValue,
                isMoving: false,
                showPicker: false
            };
        },
        options: {
            styleIsolation: 'shared'
        },
        methods: {
            cancel() {
                this.showPicker = false;
            },
            open() {
                this.showPicker = true;
            },
            pickstart(e) {
                this.isMoving = true;
            },
            pickend() {
                this.isMoving = false;
            },
            confirm() {
                if (this.isMoving) {
                    uni.$showMsg('滚动选择中,请稍后确定');
                    return;
                }
                if ('selector' === this.mode) {
                    // 单选只返回第一个
                    this.$emit('onConfirm', this.pickerValue[0]);
                }
                if ('date' === this.mode) {
                    if ('month' === this.fields) {
                        // 只需要年月
                        this.$emit('onConfirm', this.years[this.pickerValue[0]] + '-' + this.months[this.pickerValue[
                            1]]);
                    }else{
                        // 年月日
                        this.$emit('onConfirm', this.pickerValue);
                    }
                }
                if ('multiSelector' === this.mode) {
                    // 多选返回所有
                    this.$emit('onConfirm', this.pickerValue)
                }
                this.cancel();
            },
            changePicker(e) {
                const oldValue = this.pickerValue;
                this.pickerValue = e.detail.value;
                if ('multiSelector' === this.mode) {
                    // 多选级联 如果更改省份则需要更新市、区
                    oldValue.forEach((item, index) => {
                        if (item !== this.pickerValue[index]) {
                            this.$emit('columnChange', {
                                column: index,
                                value: this.pickerValue[index]
                            })
                        }
                    })
                }
            }
        }
    };
</script>

<style lang="scss">
    .picker-modal {
        z-index: 90;
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: rgba(0, 0, 0, 0.4);
    }

    .picker-content {
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 99;
        background-color: #fff;
        transition: all 0.3s;
        border-radius: 15px 15px 0 0;
        padding: 15px 10px;
        box-sizing: border-box;

        .picker-header {
            height: 100rpx;
            line-height: 100rpx;
            position: absolute;
            top: 0;
            left: 40rpx;
            right: 40rpx;

            .confirm {
                color: $font-text-color;
            }

            .title {
                font-size: 32rpx;
                font-weight: bold;
            }
        }

        .indecator {
            font-size: 50rpx;
        }

        .picker-view {
            position: relative;
            top: 60rpx;
            left: 0;
            right: 0;
            height: 490rpx;
            background-color: rgba(255, 255, 255, 1);

            .picker-item {
                line-height: 90rpx;

                // #ifdef MP-WEIXIN
                line-height: 70rpx;
                // #endif

                text-align: center;
                text-overflow: ellipsis;
            }
        }
    }
</style>

效果图如下:

单选:

image.png

时间:

image.png

多选:

image.png

来源链接:blog.csdn.net/u012830533/…

来源链接:blog.csdn.net/weixin_4689…