vue之封装预约类组件
0. 展示所有数据,【禁用】的展示【灰色】,【没选中】的展示【白色】,【选中的】时间范围展示【红色】
1. 点击两次,锁定时间范围。
2. 如果有跨越了禁用时间段的话,则重新选择。
3. 【禁用的时间范围】 和 【全部的时间范围】,后端会返回。
4. 插件会返回选择的时间。
<template>
<view class="item" v-bind:class="{active:item.active,disabled:item.disabled}" v-for="(item, index) in list"
:key="index" v-on:click="clickItem(item,index)">
<view style="display: flex;justify-content: space-between;">
<view>
{{item.time}}
</view>
<view v-if="item.disabled">
该条已被<text style="color: white;">{{item.bookedBy}}</text>预约
</view>
</view>
</view>
</template>
<!-- 预约类时间段选择组件的开发思路:
0. 展示所有数据,【禁用】的展示【灰色】,【没选中】的展示【白色】,【选中的】时间范围展示【红色】
1. 点击两次,锁定时间范围。
2. 如果有跨越了禁用时间段的话,则重新选择。
3. 【禁用的时间范围】 和 【全部的时间范围】,后端会返回。
4. 插件会返回选择的时间。
-->
<script>
export default {
// props接收两个值,禁用的时间段和全部的时间段
props: {
// 禁用的时间
checkTime: {
type: Array
},
// 所有的时间
allTime: {
type: Array
},
},
data() {
return {
// 用data接收props传来的值,不要直接操作props
// list用于存储传来的【全部的时间】,以下是传来数据的格式
// "time": "08:00-08:30", "disabled": false, "active": false
list: this.allTime,
// 【禁用的时间】
disabledList: this.checkTime,
// item 点击的次数
clickNumber: 0,
// 点击item,把下标存到数组。
indexArr: [],
}
},
created() {
this.initTime();
},
computed: {
// 计算属性,用于返回给父组件,选值的范围。
timeList() {
let list = []
this.list.forEach(item => {
if (item.active) {
list.push(item)
}
})
let obj = {
start: '',
end: ''
}
if (list.length) {
obj.start = list[0].time.split('-')[0]
obj.end = list[list.length - 1].time.split('-')[1];
}
//console.log("computed监听",obj)
return obj;
}
},
methods: {
// 通过传来的数据构建时间数组
initTime() {
// 根据【所有时间】和【禁用时间】,确定列表
this.list.forEach(item => {
this.disabledList.forEach(vitem => {
// 判断是否有list的time和disabled的time一致
// 有的话,则需要禁用掉
const hasTime = item.time == vitem.time
if (hasTime) {
item.disabled = true
}
})
})
},
clickItem(item, index) {
// 如果是disable状态,直接不让点击
if (item.disabled) {
return
}
// 点击次数增加,用于记录点击的次数
this.clickNumber++;
// 记录第一次点击,且把数组的index值,存到indexArr 里面
if (this.clickNumber == 1) {
this.indexArr.push(index)
}
// 记录第二次点击,且把数组的index值,存到indexArr 里面
if (this.clickNumber == 2) {
this.indexArr.push(index)
}
console.log(this.indexArr)
// 记录第三次点击,且把数组的index值,存到indexArr 里面
// 记录第三次的值,是为了下面重置第三次为第一次。
// 用于接下来的循环
if (this.clickNumber == 3) {
this.indexArr = [index]
}
// 给index排序
this.indexArr = this.indexArr.sort((a, b) => a - b);
// 如果点击的次数正好是第三次的时候
// 点击次数重置为1
// 我们的目的是点击两次,锁定时间范围,所以三次以上的,可以重置上面的步骤。
if (this.clickNumber % 3 == 0) {
// 重置成点击一次的状态。
this.clickNumber = 1;
// list中的active设置成false
this.list.forEach(v => v.active = false);
// 当前点击的item,设置active是true
item.active = true
}
// 验证,如果选择多个的时候,跨着disabled,则不让选择。
// 如果选择的,没有跨着disabled,则都给选择上。
this.getCheckList(item)
},
getCheckList(vitem) {
try {
console.log("getCheckList", this.list, this.indexArr)
this.list.forEach((item, idx) => {
// this.indexArr 存两个值
const [start, end] = this.indexArr
if (idx >= start && idx <= end) {
// 遍历List,如果有disabled的抛出异常。
// 如果没有,则把区间内的赋值active
if (item.disabled) {
throw new Error("包含disabled状态数据")
}
item.active = true
}
})
} catch (err) {
// 抛出异常----选中的区间内有disabled的item的时候。
// list 重置
this.list.forEach(v => v.active = false);
// 当前item为选中状态
vitem.active = true;
}
vitem.active = true;
// 返回给父组件
this.$emit('getTime', this.timeList)
}
}
}
</script>
<style>
.item {
line-height: 40px;
background: #fff;
border-bottom: 1px solid #D2D2D2;
}
.item.active {
background: darkred;
color: black;
}
.item.disabled {
background: #888888;
color: white;
}
</style>
<TimeSelection @getTime='getTime' ref="child" :allTime="timeSelectList"
:checkTime="timeSelectDisabledList" />
getTime(val) {
console.log("getTime组件选择后的结果", val)
},
// 后端返回所有的时间段列表
timeSelectList: [],
// 已选时间段列表
timeSelectDisabledList: [],