在现代Web应用中,用户界面的友好性和交互性至关重要,特别是在处理时间选择这类常见功能时。本文将详细介绍如何利用Vue.js框架结合微信小程序(uni-app)开发一个自定义的时间段选择组件。这个组件允许用户便捷地选择上午或下午的具体时间段,并计算所选时间段的总工作时长。
组件概述
本组件通过弹出层(u-popup
)展示,提供了上午和下午两个时段的选择,每个时段内有预设的开始时间选项。用户点击不同的时间选项后,组件会自动计算并显示所选时间段的工作小时数。最后,用户确认选择后,组件通过事件向外传递所选的开始时间、结束时间和总工作时长。
技术栈
- Vue.js:前端框架,用于构建组件的结构和逻辑。
- uni-app:基于Vue.js的跨平台开发框架,支持微信小程序等多端开发。
- SCSS:CSS预处理器,增强样式编写能力。
<template>
<u-popup :show="show" mode="bottom" @close="close" @open="open" :closeable="true">
<view class="">
<view class="title">选择服务时间 </view>
<view class="workTime">
<view class="t1" @click="choseType('am')">{{startTime}}</view>
<view class="t2">{{workTime}}小时</view>
<view class="t1" @click="choseType('pm')">{{endTime}}</view>
</view>
<view class="workTime">
<view :class="timeType=='am'?'t1 typecolor' :'t1'" @click="timeType='am';"
style="border: none;" >00:00-11:59</view>
<view class="t2"> </view>
<view :class="timeType=='pm'?'t1 typecolor' :'t1'" @click="timeType='pm'"
style="border: none;" >12:00-23:59</view>
</view>
<view class="timebox">
<view class="time" v-if="timeType=='am'">
<view v-for="(item,index) in amlist" :key="index" :class="startTime==item ? 'activetime' : ''"
@click="changetime(item,'am')">
{{item}}
</view>
</view>
<view class="time" v-if="timeType=='pm'">
<view v-for="(it,i) in pmlist" :key="'pm'+i" :class="endTime==it ? 'activetime' : ''"
@click="changetime(it,'pm')">
{{it}}
</view>
</view>
</view>
<view class="woodsbtn btn" @click="handleTime">
确定
</view>
</view>
</u-popup>
</template>
<script>
import calculateTimeDifference from "@/utils/calculateTimeDifference.js"
export default {
name:"choseTime",
data() {
return {
show:true,
startTime:"",
endTime:"",
amlist:["7:00","7:30","8:00","8:30"],
pmlist:["12:00","13:30","14:00","19:30"],
workTime:"0",
timeType:"am"
};
},
methods:{
handleTime(){
if(this.workTime==0){
uni.showToast({
title:'请选择服务时间',
icon:'none'
})
return
}
this.$emit('handleTime',{
startTime:this.startTime,
endTime:this.endTime,
workTime:this.workTime
})
this.show = false
},
open() {
// console.log('open');
},
close() {
this.show = false
},
choseType(type){
this.timeType=type
},
changetime(item,type){
if (type=='am') {
this.startTime=item
this.timeType='pm'
}else if (type=='pm') {
this.endTime=item
}
if(this.startTime && this.endTime){
this.workTime=calculateTimeDifference(this.startTime,this.endTime)
}
},
}
}
</script>
<style scoped lang="scss">
.title{
text-align: center;
line-height: 50rpx;
font-weight: bold;
padding: 30rpx;
}
.workTime{
display: flex;
align-items: center;
justify-content: center;
padding: 20rpx;
.t1{
border-bottom: 1px solid #EEEEEE;
width: 220rpx;
margin: 0 30rpx;
height:60rpx;
text-align: center;
}
.t2{
height: 60rpx;
width: 160rpx;
text-align: center;
font-size: 28rpx;
color: #999999;
}
.typecolor{
font-weight: bold;
font-size: 32rpx;
color: #277EEF;
}
}
.timebox{
padding: 10rpx 0;
.timetitile{
font-size: 36rpx;
font-weight: bold;
padding: 0 30rpx;
}
.time{
display: flex;
align-items: center;
flex-wrap: wrap;
margin-top: 20rpx;
margin-bottom: 60rpx;
>view{
// width: 120rpx;
padding:20rpx 35rpx;
margin: 15rpx;
// height: 60rpx;
background-color: #F2F2F2;
border-radius: 8rpx
}
.activetime{
border: 1px solid #277EEF;
color: #277EEF;
}
}
}
.chosetime{
position: fixed;
left: 5%;
bottom: 80rpx;
width: 90%;
background: linear-gradient(#FF7134,#FF3A3E);
border-radius:20rpx;
padding: 20rpx;
display: flex;
align-items: center;
justify-content: space-between;
.tleft{
color: #fff;
text{
font-size: 36rpx;
color: #fff;
}
}
.tright{
width: 200rpx;
height:80rpx;
background: #ffc368;
border-radius: 12rpx;
text-align: center;
line-height: 80rpx;
color: #594423;
}
}
.btn{
width: 90%;
margin-bottom: 40rpx;
}
</style>
组件结构与实现
模板(Template)
模板部分使用Vue的模板语法定义了组件的HTML结构。包括标题、时间选择区域、时间列表、确认按钮等元素。通过绑定不同的数据属性和事件监听器,实现了动态渲染和交互逻辑。
脚本(Script)
脚本部分包含组件的逻辑代码,主要涉及以下几个方面:
- 数据绑定:定义了组件所需的数据属性,如
show
控制弹窗显示状态,startTime
和endTime
分别存储所选的开始和结束时间,以及时间列表和工作时长等。 - 方法定义:
handleTime
:用户点击确定按钮时触发,检查是否选择了时间,然后通过事件向父组件传递选择结果。open
和close
:处理弹窗的打开和关闭逻辑。choseType
:根据用户点击上午或下午,改变当前时间类型。changetime
:根据用户选择的时间更新开始或结束时间,并计算工作时长。
- 计算工作时长:引入了一个外部工具函数
calculateTimeDifference
来计算两个时间点之间的时差。
样式(Style)
使用SCSS编写组件样式,确保组件在不同设备上都能呈现良好的视觉效果。包括标题样式、时间选择区域布局、时间按钮的激活状态等。
关键技术点
- 条件渲染:利用Vue的
v-if
和v-for
指令,根据timeType
的值动态渲染上午或下午的时间列表。 - 事件处理:通过
@click
绑定事件监听器,实现时间选择和确定按钮的功能。 - 外部工具函数:引入外部JS文件计算时间差,保持业务逻辑的清晰分离。
该函数用于计算两个时间字符串之间的时间差。它首先将时间字符串转换为分钟数,然后计算时间差(以分钟为单位),最后将时间差转换回"HH:mm"格式并返回。
calculateTimeDifference.js
function calculateTimeDifference(startTime, endTime) {
/**
* 计算两个时间字符串之间的时间差。
*
* 参数:
* - startTime (string): 开始时间,格式为 "HH:mm"。
* - endTime (string): 结束时间,格式为 "HH:mm"。
*
* 返回:
* - string: 时间差,格式为 "HH:mm"。
*
* 示例:
* - 输入 "8:30", "9:45" 返回 "1:15"
*/
// 将时间字符串转换为分钟数
function timeToMinutes(timeStr) {
const [hours, minutes] = timeStr.split(':').map(Number);
return hours * 60 + minutes;
}
// 计算时间差(以分钟为单位)
const startMinutes = timeToMinutes(startTime);
const endMinutes = timeToMinutes(endTime);
const diffMinutes = endMinutes - startMinutes;
// 将时间差转换回"HH:mm"格式
function minutesToTime(minutes) {
const hours = Math.floor(minutes / 60);
const mins = minutes % 60;
return `${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}`;
}
return minutesToTime(diffMinutes);
}
export default calculateTimeDifference;
// 使用示例
// const startTime = "8:30";
// const endTime = "9:45";
// const totalTimeDiff = calculateTimeDifference(startTime, endTime);
// console.log(totalTimeDiff); // 输出 "1:15"
结语
通过上述步骤,我们成功创建了一个灵活且易用的时间段选择组件,它不仅提升了用户体验,也展示了Vue.js在构建复杂UI组件方面的强大能力。此组件可以广泛应用于需要精确时间选择的场景,如预约服务、会议安排等。希望本文能为开发者在实现类似功能时提供一定的参考和启发。