uniapp中使用picker-view选择时间

picker-view 是 UniApp 中用于展示和选择数据的组件。它适用于创建多列选择器,类似于 iOS 和 Android 系统中的选择器视图。以下是 picker-view 的详细介绍,包括用法、属性和事件。

一 用法

html 复制代码
<template>
  <view>
    <picker-view :value="value" @change="onChange" :indicator-style="indicatorStyle">
      <picker-view-column v-for="(column, index) in columns" :key="index">
        <view v-for="(item, itemIndex) in column" :key="itemIndex">{{ item }}</view>
      </picker-view-column>
    </picker-view>
  </view>
</template>
javascript 复制代码
<script>
export default {
  data() {
    return {
      value: [0, 0], // 选中的值对应列中的索引
      columns: [     // 列数据
        ['Option 1', 'Option 2', 'Option 3'],
        ['Item 1', 'Item 2', 'Item 3']
      ],
      indicatorStyle: 'height: 50px; line-height: 50px;' // 指示器样式
    };
  },
  methods: {
    onChange(e) {
      this.value = e.detail.value; // 更新选中的值
      console.log('Selected value:', this.value);
    }
  }
};
</script>
javascript 复制代码
<style scoped>
/* 可以根据需要添加自定义样式 */
</style>

二 主要属性

  • value: 数组,表示当前选中的索引值。数组的长度应与 columns 的列数一致。例如,如果有两列,每列的选项数组长度分别为 3 和
    3,则 value 应该是 [0, 0] 表示两列的默认选中项索引。
  • indicator-style: 字符串,用于设置选择器的指示器样式。可以设置如高度、背景颜色等样式。

三 主要事件

change: 当用户选择了新项时触发。事件对象的 detail.value 是更新后的选中值数组。例如:

javascript 复制代码
onChange(e) {
  this.value = e.detail.value;
  console.log('Selected value:', this.value);
}
  • picker-view-column 是 picker-view 的子组件,每个 picker-view-column 代表一个列。
  • v-for 指令用于遍历 columns 和列中的选项数据。
  • e.detail.value 是一个数组,表示用户选择的每一列的索引。

四 应用场景

  • 选择日期和时间
  • 选择地区(省市区)
  • 多级分类选择

五 案例

需求 :购买商品时,可以选择取货时间,点击向右的箭头可以显示选择预约取货时间弹窗。第一次进入弹窗,默认回显当前时间,选择时间后,回显选择的时间

父组件在打开弹框时,会传一个当前时间给子组件,子组件在初始化时,根据当前时间进行回显。

根据传过来的时间,拿到月,时,分,然后分别在days,hours,minutes中找到对应的index,在分别把index push到value中

javascript 复制代码
  let dayIndex = this.days.findIndex((item) => item === objTimeDay);
            let hourIndex = this.hours.findIndex((item) => item === objTimeHour);
            let minuteIndex = this.minutes.findIndex((item) => item === objTimeMinute);
            if (dayIndex > -1) {
                this.value[0] = dayIndex;
            }
            if (hourIndex > -1) {
                this.value[1] = hourIndex;
            }
            if (minuteIndex > -1) {
                this.value[2] = minuteIndex;
            }


完整代码

父组件

javascript 复制代码
// 引用
import selectTime from './selectTime/index.vue';
//注册
 components: { selectAddress, selectShop, selectTime },
//使用
 <select-time ref="selectTime" @getSelectTime="getSelectTime"></select-time>

openSelectTimePopup() {
            this.$refs.selectTime.open(this.selectTimeInfo);
        },
 // 自定义事件
getSelectTime(obj) {
   this.selectTimeInfo = obj;
},

selectTime 弹窗

javascript 复制代码
<template>
    <uni-popup ref="selectTime" type="bottom" :maskClick="true">
        <view class="main">
            <view class="main-header">
                <view class="main-header-title">预约取货时间</view>
                <view class="main-header-image" @click="close">
                    <image src="@/static/image/cart/sureOrder/close.png"></image>
                </view>
            </view>
            <view class="main-time">
                <picker-view v-if="visible" :indicator-style="indicatorStyle" :value="value" @change="bindChange" class="picker-view">
                    <picker-view-column>
                        <view class="item" v-for="(item, index) in days" :key="index">{{ item }}</view>
                    </picker-view-column>
                    <picker-view-column>
                        <view class="item" v-for="(item, index) in hours" :key="index">{{ item }}</view>
                    </picker-view-column>
                    <picker-view-column>
                        <view class="item" v-for="(item, index) in minutes" :key="index">{{ item }}</view>
                    </picker-view-column>
                </picker-view>
            </view>
            <view class="main-button" @click="confirm">确认</view>
        </view>
    </uni-popup>
</template>

<script>
export default {
    data() {
        return {
            days: [],
            hours: [],
            minutes: [],
            day: '',
            hour: '',
            minute: '',
            visible: true,
            value: [],
            indicatorStyle: `height: 50px;`,
            selectTimeInfo: {
                name: '',
                time: ''
            }
        };
    },
    methods: {
        confirm() {
            this.day = this.days[this.value[0]];
            this.hour = this.hours[this.value[1]];
            this.minute = this.minutes[this.value[2]];
            this.selectTimeInfo.name = this.day + ' ' + this.hour + ':' + this.minute;
            let currentDate = new Date();
            currentDate.setDate(currentDate.getDate() + this.value[0]);
            let selectYear = currentDate.getFullYear();
            let selectTimeMonth = currentDate.getMonth() + 1 < 10 ? '0' + (currentDate.getMonth() + 1) : currentDate.getMonth() + 1;
            let selectTimeDay = currentDate.getDate() < 10 ? '0' + currentDate.getDate() : currentDate.getDate();
            let time = selectYear + '-' + selectTimeMonth + '-' + selectTimeDay + ' ' + this.hour + ':' + this.minute;
            this.selectTimeInfo.time = time.slice(0, 16)+':' + '00';
            this.$emit('getSelectTime', this.selectTimeInfo);
            this.close();
        },
        init(obj) {
            // day
            for (var i = 0; i < 5; i++) {
                let date = new Date();
                let day;
                if (i === 0) {
                    day = '今天';
                } else if (i === 1) {
                    day = '明天';
                } else {
                    date.setDate(date.getDate() + i);
                    let month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
                    let d = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
                    day = month + '月' + d + '日';
                }
                this.days.push(day);
            }
            let currentDate = new Date();
            let currentMonth = currentDate.getMonth() + 1;
            let currentDay = currentDate.getDate();

            let selectTime = obj.time;
            let objTimeDate = new Date(selectTime);
            let selectMonth = objTimeDate.getMonth() + 1;
            let selectDay = objTimeDate.getDate();

            let objTimeDay;

            if (currentMonth === selectMonth && currentDay === selectDay) {
                objTimeDay = '今天';
            } else if (currentMonth === selectMonth && currentDay + 1 === selectDay) {
                objTimeDay = '明天';
            } else {
                let month = selectMonth < 10 ? '0' + selectMonth + '月' : selectMonth + '月';
                let day = selectDay < 10 ? '0' + selectDay + '日' : selectDay + '日';
                objTimeDay = month + day;
            }
            let objTimeHour = objTimeDate.getHours() < 10 ? '0' + objTimeDate.getHours() : objTimeDate.getHours();
            let objTimeMinute = objTimeDate.getMinutes() < 10 ? '0' + objTimeDate.getMinutes() + '分' : objTimeDate.getMinutes() + '分';
            this.hours = this.getHoursRange(0, 24);
            this.minutes = this.getMinuteRange(0, 61);
            let dayIndex = this.days.findIndex((item) => item === objTimeDay);
            let hourIndex = this.hours.findIndex((item) => item === objTimeHour);
            let minuteIndex = this.minutes.findIndex((item) => item === objTimeMinute);
            if (dayIndex > -1) {
                this.value[0] = dayIndex;
            }
            if (hourIndex > -1) {
                this.value[1] = hourIndex;
            }
            if (minuteIndex > -1) {
                this.value[2] = minuteIndex;
            }
        },
        getHoursRange(startHour, endHour) {
            const hours = [];
            for (let i = startHour; i <= endHour; i++) {
                let hour = i < 10 ? '0' + i : i;
                hours.push(hour);
            }
            return hours;
        },
        getMinuteRange(startMinute, endMinute) {
            let minutes = [];
            for (var i = startMinute; i < endMinute; i++) {
                let minute = i < 10 ? '0' + i + '分' : i + '分';
                minutes.push(minute);
            }
            return minutes;
        },
        bindChange(e) {
            const val = e.detail.value;
            this.value[0] = val[0];
            this.value[1] = val[1];
            this.value[2] = val[2];
        },
        open(obj) {
            this.$refs.selectTime.open();
            this.init(obj);
        },
        close() {
            this.$refs.selectTime.close();
        }
    }
};
</script>

<style lang="scss" scoped>
.main {
    width: 100%;
    height: 732rpx;
    border-radius: 32rpx 32rpx 0px 0px;
    background-color: #fff;
    box-sizing: border-box;
    .main-header {
        padding: 40rpx 0 0 40rpx;
        display: flex;
        align-items: center;
        justify-content: space-between;
        .main-header-title {
            font-family: Source Han Sans CN, Source Han Sans CN;
            font-weight: bold;
            font-size: 36rpx;
            color: #333333;
            text-align: left;
            font-style: normal;
            text-transform: none;
        }
        .main-header-image {
            width: 48rpx;
            height: 48rpx;
            margin-right: 40rpx;
            image {
                width: 100%;
                height: 100%;
            }
        }
    }
    .main-time {
        width: 100%;
        height: 400rpx;
        margin-top: 80rpx;
        .picker-view {
            width: 100%;
            height: 300rpx;
            margin-top: 20rpx;
        }
        .item {
            line-height: 100rpx;
            text-align: center;
        }
    }
    .main-button {
        width: 496rpx;
        height: 80rpx;
        background: #c11920;
        border-radius: 80rpx;
        font-family: Source Han Sans CN, Source Han Sans CN;
        font-weight: 400;
        font-size: 32rpx;
        color: #ffffff;
        line-height: 80rpx;
        text-align: center;
        font-style: normal;
        text-transform: none;
        margin: 40rpx auto 0 auto;
    }
}
</style>

如果需要设置不能选择之前的时间,可以拿到当前时间的时,分,来设置

javascript 复制代码
 if (objTimeDay === '今天') {
        this.hours = this.getHoursRange(currentHour, 24);
        this.minutes = this.getMinuteRange(currentMinute, 61);
 } else {
        this.hours = this.getHoursRange(0, 24);
        this.minutes = this.getMinuteRange(0, 61);
 }

 getHoursRange(startHour, endHour) {
            const hours = [];
            for (let i = startHour; i <= endHour; i++) {
                let hour = i < 10 ? '0' + i : i;
                hours.push(hour);
            }
            return hours;
        },
 getMinuteRange(startMinute, endMinute) {
            let minutes = [];
            for (var i = startMinute; i < endMinute; i++) {
                let minute = i < 10 ? '0' + i + '分' : i + '分';
                minutes.push(minute);
            }
            return minutes;
        },
相关推荐
小白小白从不日白20 分钟前
react hooks--useCallback
前端·react.js·前端框架
恩婧28 分钟前
React项目中使用发布订阅模式
前端·react.js·前端框架·发布订阅模式
mez_Blog29 分钟前
个人小结(2.0)
前端·javascript·vue.js·学习·typescript
珊珊而川37 分钟前
【浏览器面试真题】sessionStorage和localStorage
前端·javascript·面试
森叶1 小时前
Electron 安装包 asar 解压定位问题实战
前端·javascript·electron
drebander1 小时前
ubuntu 安装 chrome 及 版本匹配的 chromedriver
前端·chrome
软件技术NINI1 小时前
html知识点框架
前端·html
深情废杨杨1 小时前
前端vue-插值表达式和v-html的区别
前端·javascript·vue.js
GHUIJS1 小时前
【vue3】vue3.3新特性真香
前端·javascript·vue.js
markzzw1 小时前
我在 Thoughtworks 被裁前后的经历
前端·javascript·面试