封装一个小程序日期(日历)时间 选择器组件
简要说明:
一共两个版本 ,date-time-picker 和 date-time-picker-plus.
date-time-picker 弹窗层是 基于 vant-weapp 的 van-popup 组件实现的
date-time-picker-plus 弹窗层是 基于 小程序 自带的 page-container 组件来实现的
*注意:date-time-picker 需要下载 vant-weapp 组件库配合一起使用,date-time-picker-plus 可以直接在小程序里面使用
首先看一下效果图
组件代码
两个版本代码几乎一样,只是弹窗层用的不一样,这里我就用 基于 vant-weapp UI一起使用的版本来写
- wxml 中
<view class="date-time-picker-box"> <van-popup show="{{ show }}" zIndex="9999" round position="bottom" custom-style="border-radius:16px 16px 0 0;min-height:355px;max-height:400px;" bind:close="handleCancel"> <view class="date-time-picker-title"> <view class="date-time-picker-nav"> <view bindtap="handleChangeTag" data-index="0" class="tag date-tag {{currentIndex == 0 ? 'active' : ''}}"> {{year}}年{{month}}月{{day}}日 </view> <view bindtap="handleChangeTag" data-index="1" class="tag time-tag {{currentIndex == 1 ? 'active' : ''}}"> {{hour}}:{{minute}} </view> <view class="date-time-line" style="left:{{left}}px;width: {{width}}px;"></view> </view> <button bindtap="handleConfirm" class="date-picker-oper-btn">确定</button> </view> <view class="date-time-picker-content"> <!-- 日历主体 --> <swiper current="{{currentIndex}}" style="height:100%;"> <swiper-item catchtouchmove="catchtouchmove"> <view class="swiper-item "> <!-- 日历组件 --> <calendar bindselectDay="selectDay" bindgetDateList="getDateList" vertical="{{vertical}}"></calendar> </view> </swiper-item> <swiper-item catchtouchmove="catchtouchmove"> <view class="swiper-item "> <div class="date-time-item"> <picker-view indicator-style="height: 50px;" style="width: 100%; height: 200px;text-align:center;" value="{{value}}" bindpickstart="bindpickstart" bindpickend="bindpickend" bindchange="bindChange"> <picker-view-column> <view wx:for="{{hours}}" wx:key="*this" style="line-height: 50px">{{item}}时</view> </picker-view-column> <picker-view-column> <view wx:for="{{minutes}}" wx:key="*this" style="line-height: 50px"> {{item}}分 </view> </picker-view-column> </picker-view> </div> </view> </swiper-item> </swiper> </view> </van-popup></view>
- wxss 中
.date-time-picker-box .date-time-picker-title { display: flex; align-items: center; justify-content: space-between; padding: 0rpx 48rpx; height: 112rpx; box-sizing: border-box; border-bottom: 2rpx solid #E5E3E3; max-height: 400px; }.date-time-picker-box .date-time-picker-title .title-txt { font-size: 17px; font-weight: 500; color: #1F1E1E;}.date-time-picker-box .date-time-picker-title .date-picker-oper-btn { width: 104rpx; height: 64rpx; line-height: 64rpx; text-align: center; font-size: 28rpx; border-radius: 8rpx; font-weight: 500; margin: 0; padding: 0; color: var(--themeTxtColor); background-color: var(--themeColor);}.date-time-picker-box .date-time-picker-title .cancel-btn { color: #5C5959; background-color: #fff; text-align: left;}.date-time-picker-box .date-time-picker-title .date-time-picker-nav { position: relative; display: flex; align-items: center; font-weight: 500; color: #8F8D8D; height: 100%;}.date-time-picker-box .date-time-picker-nav .date-tag { margin-right: 32rpx;}.date-time-picker-box .date-time-picker-nav .tag { height: 100%; display: flex; align-items: center; justify-content: center;}.date-time-picker-box .date-time-picker-nav .tag.active { color: #1F1E1E;}.date-time-picker-box .date-time-picker-nav .date-time-line { position: absolute; bottom: 0; width: 40rpx; height: 4rpx; background-color: #5C5959; transition: all 0.3s linear;}.date-picker-btn-box { display: flex; font-weight: 600; margin-top: 40rpx; color: var(--themeColor); justify-content: space-around;}.date-time-picker-content { height: 600rpx; box-sizing: border-box;}
- json 中
{ "component": true, "usingComponents": { "van-popup": "@vant/weapp/popup/index", "calendar":"./calendar/index" }}
- js 中
const date = new Date(); // 获取系统日期var getYear = date.getFullYear(), getMonth = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1, getDate = date.getDate() < 10 ? "0" + date.getDate() : date.getDate(), isScroll = false;Component({ properties: { show: { // 控制弹窗显示和隐藏 type: Boolean, value: false, }, vertical: { // 是否垂直滑动 type: Boolean, value: false, }, type: { type: String, value: "part", // time 和 part }, }, data: { year: getYear, // 当前已选年份,默认是当年 month: getMonth, // 当前已选月份,默认是当月 day: getDate, // 当前已选天,默认是当天 hour: "09", // 当前已选小时, 默认 09 点 minute: "00", // 当前已选分钟,默认00 hours: [], // 时间选择器,存放的小时数组 0 - 23 minutes: [], // 时间选择器,存放的分钟数组 00 和 30 或者 00 - 59 value: [0, 0], // 时间选择器,当前选择时间 索引 currentIndex: 0, // tab导航当前索引 left: 0, // tab导航 底部线条 当前离左侧位置 距离 width: 123, // tab导航 底部线条 当前 宽度 firstEnter: true, // 是否第一次打开, 默认true }, lifetimes: { attached: function () { this.initDateTimePicker(); }, moved: function () {}, detached: function () {}, }, methods: { // 日期改变的回调 selectDay({ detail }) { console.log(detail, "selectDay detail"); let { year, month, day } = detail; month = month > 9 ? month : "0" + month; day = day > 9 ? day : "0" + day; if (!this.data.firstEnter) { setTimeout(() => { this.setData({ currentIndex: 1 }); this.changeline(); }, 300); } this.setData({ year, month, day, firstEnter: false }); }, // 切换导航 handleChangeTag(e) { this.setData({ currentIndex: e.currentTarget.dataset.index, firstEnter: false, }); this.changeline(); }, // 渲染横线位置的方法 changeline() { let _this = this; // SelectorQuery.in(Component component): 将选择器的选取范围更改为自定义组件 component 内 let query = wx.createSelectorQuery().in(this); // select() 在当前页面下选择第一个匹配选择器 selector 的节点 // boundingClientRect() 添加节点的布局位置的查询请求。相对于显示区域,以像素为单位 query.select(".active").boundingClientRect(); // SelectorQuery.exec(function callback) 执行所有的请求 // 请求结果按请求次序构成数组,在callback的第一个参数中返回 query.exec(function (res) { // console.log(res); _this.setData({ left: res && res[0].left - 24, width: parseInt(res[0].width), }); }); }, bindChange(e) { const val = e.detail.value; this.setData({ hour: this.data.hours[val[0]], minute: this.data.minutes[val[1]], }); }, // 滚动开始 bindpickstart() { isScroll = true; }, //滚动结束 bindpickend() { isScroll = false; }, // 点击取消按钮,关闭日期选择器 handleCancel() { this.setData({ show: false }); }, // 点击确定按钮 handleConfirm() { let { year, month, day, hour, minute } = this.data; // console.log(year, month, day, hour, minute) // 判断用户选择时间滚动是否结束,解决 picker-view bindChange 延迟问题 if (isScroll) return; const timeStr = year + "-" + month + "-" + day + " " + hour + ":" + minute; this.triggerEvent("onSelectDate", timeStr); this.setData({ show: false, currentIndex: 0 }); this.changeline(); }, // 初始化 picker 时间数据 initDateTimePicker() { let hours = [], minutes = []; // 存放小时的数组 for (let i = 0; i <= 23; i++) { if (i < 10) { i = "0" + i; } hours.push(i); } // 存放分钟的数组 if (this.data.type === 'time') { for (let i = 0; i <= 59; i++) { if (i < 10) { i = '0' + i } minutes.push(i) } } else { minutes = ['00', '30'] } this.setData({ hours, minutes }); this.setData({ value: [9, 0] }); }, // 加载日历数据 getDateList() { // 防止滑动时 tab导航切换到时间模块 this.setData({ firstEnter: true }); }, // 禁止 日期时间 swiper 滑动 catchtouchmove() { return false; }, },});
简要说明:
在 index.wxml 文件 中 ,会有一个 日历组件
这个组件会放在 date-time-picker 组件目录下,这里我就不把代码贴出来了,可以直接去我的远程仓库去拉取。
组件代码仓库地址:Gitee | Github 或者直接复制下面的链接 直接下载代码
- Gitee 远程仓库下载链接
git clone https://gitee.com/junfeng535/wx-date-time-picker.git
- Github 远程仓库下载链接
git clone https://github.com/junfeng-git/wx-date-time-picker.git
来源地址:https://blog.csdn.net/m0_49045925/article/details/129195068