使用VUE封装一年中的月份段,和一天中的小时段组件
需求:后台返回数据,数据为一天中的几点到几点。或一年中的几月到几月。要求前端页面显示该时间段的状态为选中状态。并可以重新进行选择。将新的时间段返回到后台进行更改
例如:
{
startTime:01:00,
endTime:18:00
}
首先放上我的图,有点丑。哈哈。
实现思路
1.首先将具有这个功能的模块封装成组件的形式。并且建立它与父组件之间的通信。
2.其次使用v-model为每一个“时间点”(每一个小块)绑定数据。
3.最后在点击事件中操作数据改变“时间点”的状态即可。
上代码
//父组件代码
<template>
<div class="TimeFenceBox">
//在这里使用子组件,@childMsg="listenChildMsg"用来监测子组件选择完成后传递过来的值。
//:parentObj='timerId'用来将父组件上的数据发送给子组件。
<timerChoose @childMsg="listenChildMsg" :parentObj='timerId'></timerChoose>
</div>
</template>
<script>
//这里先引入子组件
import timerChoose from "@/components/chooseTimer/chooseTimer"; //时间选择组件
export default {
//注册子组件
components: {
timerChoose,
},
data() {
return {
startTime:'',
endTime: "",
//传递给子组件的时间段
timerId: {
startTime: "",
endTime: ""
}
};
},
created() {
//先执行自身的查询方法
this.getList();
},
methods: {
//获取详情
getList() {
let that = this;
this.$axios
.post(
"/apis/xxx/xxx/xxx",
{
xxx: xxx,
xxx: xxx,
},
{
headers: {
"X-Zc-User-Id": that.userId,
}
}
)
.then(res => {
//这里将拿到的数据赋值给要传递给子组件的变量。
that.timerId.startTime = res.startTime
that.timerId.endTime = res.endTime
});
},
// 这里的方法是子组件执行完选择时间段的操作后,点击确定按钮向父组件传递的数据
listenChildMsg(v1, v2) {
this.startTime = v1;
this.endTime = v2;
}
}
};
// 子组件时间段选择器代码
<template>
<div class="timerChoose">
//这里通过绑定数组对象进行循环遍历的方式来创建各个时间点的块。因为选中状态和不选中状态的样式不一样,所以
//对他的class进行动态的绑定。
<div class="timerItem" v-for="item in timerList" :key="item.id" :class="item.className" @click="handClick(item)">
{{item.text}}
</div>
</div>
</template>
<script>
export default {
//这里接收来自父组件传递的数据
props:{
parentObj:{
type:Object,
default:'',
}
},
data() {
return {
//这里定义一个数组对象。
timerList:[
{
id:1, //它的作用是用来记录块的下标
className:'', //他的作用是绑定动态的class名字。体现选中与不选中状态
text:'01:00' //时间块上显示的内容
},
{
id:2,
className:'',
text:'02:00'
},
{
id:3,
className:'',
text:'03:00'
},
......//这里需要24个。剩余的省略。自行补充。
],
clickNum:0,//记录点击的次数
chooseList:[],//记录选取的时间段
firstId:'',//记录第一次点击的ID
lastId:'',//记录第二次点击的ID
clickArr:[],//记录选中的块。并把他们的id存到该数组中
}
},
created() {
//首先拿到父元素传递过来的数据。
this.firstId = this.parentObj.startTime;
this.lastId = this.parentObj.endTime;
},
mounted() {
//在mounted中执行显示默认时间的方法。注意这里不能再created中执行。因为created中dom并未被创建。
//所以无法为其动态绑定class
this.showTimer();
},
methods: {
//默认显示时间
showTimer(){
let _this = this;
//先定义一个空数组用来装父组件传递过来的时间段
var newArr = [];
/*
假如父组件此时传递的数据是:{startTime:05:00,endTime:18:00}
这里就要先将数据类型转化为整形。具体的转化方式网上很多。这里不再赘述。转完之后的数据为
{startTime:5,endTime:18}
*/
//循环遍历父组件传递的时间点。将他们之间的时间都放在提前定义好的空数组newArr中。
for(var i=this.firstId;i<=this.lastId+1;i++){
//5点到18点之间的时间点都作为数组的元素进行保存。
newArr.push(i);
//newArr=[5,6,7,8,9,10,11,12,13,14,15,16,17,18]
}
//循环遍历时间块的数组对象。
this.timerList.forEach(element => {
//element就是每一个时间块
/*
...
{
id:2,
className:'',
text:'02:00'
}
...
*/
//在循环24个对象的内层对上边newArr进行循环。
for(var j=0;j<newArr.length;j++){
//将element中的id属性与父组件传过来的时间段进行对比。
if(element.id==newArr[j]){
//如果相同,就把时间块中的className重新进行赋值。定为选中状态。
/*
.active{
background: #2749F3;
color: #ffffff;
}
*/
element.className = 'timerItem active';
}
}
});
}
// 点击选择时间的方法
handClick(e){
//这是每个时间块的点击事件。e表示当前被点击的元素。可以拿到当前被点击元素的属性
let _this=this;
//首先进行点击次数的操作。第一次点击,当前被点击元素变为被选中状态。第二次点击,当前被点击元素与第一次被点击
//元素之间的所有元素都变为被选中状态
//首先判断点击次数是否为零
if(this.clickNum==0){
//先把所有的选中状态清掉
_this.timerList.forEach(element => {
element.className = 'timerItem';
})
//第一次被点击的元素className被变为选中状态
e.className = 'timerItem active';
//点击次数自加一次
_this.clickNum++;
//记录第一次被点击的元素ID
_this.firstId=e.id;
}else if(this.clickNum==1){//第二次被点击的情况
e.className = 'timerItem active';//先把当前元素的状态改为选中状态
var cid = '';//这里要进行一个数据的比对。要将小的一个时间点作为startTime。
//所以需要将第一次点击的时间点与本次点击的时间点做对比
if(e.id>_this.firstId){
_this.lastId=e.id;
}else if(e.id<_this.firstId){
cid = _this.firstId;
_this.firstId = e.id;
_this.lastId = cid;
}
//将第一次点击的元素ID与第二次点击的元素ID之间的元素放到被点击元素的数组中,因为上面已经对
//第一次点击和第二次点击的元素ID进行了比对和重新赋值,所以较小的在前。较大的一个在后。
for(var i = _this.firstId ; i<= _this.lastId; i++){
_this.clickArr.push(i);
/*
假设第一次点击的元素为04:00,第二次点击的元素为18:00,
那么这里的数组为clickArr=[4,5,6,7,8,9,10,11,12,13,14,15,16,,17,18]
*/
}
//循环所有的时间块元素
_this.timerList.forEach(element => {
//循环点击两次之后,被放入点击点之间的元素数组
for(var j=0;j<=_this.clickArr.length;j++){
//进行比对。如果他们的ID相等
if(element.id == _this.clickArr[j]){
//就将元素标为被选中状态
element.className = 'timerItem active';
}
}
//第二次点击之后要将点击次数清零
_this.clickNum=0;
});
//将两次点击选中的时间点发送给父组件。由父组件执行下一步操作
this.$emit('childMsg', _this.firstId,_this.lastId+1)
//两次点击过后将选中的元素数组清零
_this.clickArr=[];
//将记录第一次点击元素的ID和第二次点击元素的ID清空
_this.lastId='';
_this.firstId='';
}
},
},
}
</script>
<style scoped>
.timerChoose{
width: 80%;
height: 100%;
display: flex;
justify-content:space-around;
flex-wrap: wrap;
}
.timerItem{
width: 15%;
height: 20%;
background: #cccccc;
text-align: center;
display: flex;
justify-content: space-around;
flex-direction: column;
font-size: 1rem;
border-radius: 1rem;
}
.active{
background: #2749F3;
color: #ffffff;
}
</style>