封装一个小程序日期(日历)时间 选择器组件
简要说明:
一共两个版本 ,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一起使用的版本来写文章来源:https://www.toymoban.com/news/detail-789338.html
- 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;
/* overflow: hidden; */
}
.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 时间类型 分钟, 支持两种类型 time 和 part , 默认是part
* time : 2023-02-03 09:00 正常的日期时间 (例如: 09:30 、11:10 、12:36 ...)
* part : 2023-02-03 09:00 分钟只包含 00 和 30 (例如: 09:30 、11:00 、12:30 ...)
*/
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),
});
});
},
/***
* 滚动选择时触发change事件,
* 可以查看小程序官方文档了解
*/
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 文件 中 ,会有一个 日历组件<calendar bindselectDay="selectDay" bindgetDateList="getDateList" vertical="{{vertical}}"></calendar>
这个组件会放在 date-time-picker 组件目录下,这里我就不把代码贴出来了,可以直接去我的远程仓库去拉取。
组件代码仓库地址:Gitee | Github 或者直接复制下面的链接 直接下载代码文章来源地址https://www.toymoban.com/news/detail-789338.html
- 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
到了这里,关于小程序日期(日历)时间 选择器组件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!