基于picker-view 封装的 vue3 uniapp小程序

image.png
<!-- 自定义三级联动日期选择器 -->
<template>
<view>
<view class="header">
<view
:class="dataType=='start'?'data choose':'data'"
@click="chooseData('start')"
>{{ start?start:'开始日期' }}</view>
<view class="heng"></view>
<view
:class="dataType=='end'?'data choose':'data'"
@click="chooseData('end')"
>{{ end?end:'结束日期'}}</view>
</view>
<view class="picker-box">
<picker-view
indicator-class="indicatorClass"
mask-class="mask-class"
:indicator-style="indicatorStyle"
:value="valueIndex"
@change="bindChange"
class="picker-view"
>
<picker-view-column class="view-column first">
<view
v-for="(item,index) in years"
:key="index"
class="item"
:class=" valueIndex[0] == index ? 'choose' : ' ' "
>{{item}}</view>
</picker-view-column>
<picker-view-column>
<view
v-for="(item,index) in months"
:key="index"
class="item"
:class=" valueIndex[1] == index ? 'choose' : ' ' "
>{{item}}</view>
</picker-view-column>
<picker-view-column class="view-column third">
<view
v-for="(item,index) in days"
:key="index"
class="item"
:class=" valueIndex[2] == index ? 'choose' : ' ' "
>{{item}}</view>
</picker-view-column>
</picker-view>
</view>
</view>
</template>
<script setup>
import { ref, reactive, toRefs, onBeforeMount, onMounted, watch } from "vue";
onBeforeMount(() => {});
onMounted(() => {
getDay();
valueIndex.value = [
years.value.indexOf(year.value),
months.value.indexOf(month.value),
days.value.indexOf(day.value)
];
});
const props = defineProps({
newDay: {
type: Number
}
});
//监听重置
watch(
() => props.newDay,
(newVal, oldVal) => {
if (newVal) {
start.value = null;
end.value = null;
dataType.value = "";
year.value = date.getFullYear();
month.value = date.getMonth() + 1;
day.value = date.getDate();
getDay();
valueIndex.value = [
years.value.indexOf(year.value),
months.value.indexOf(month.value),
days.value.indexOf(day.value)
];
}
}
);
const start = ref(null);
const end = ref(null);
const dataType = ref("");
const emit = defineEmits(["changeData"]);
//点击选择与回显
const chooseData = type => {
dataType.value = type;
if (type == "start") {
console.log(start.value, "start.value");
if (start.value) {
valueIndex.value = [
years.value.indexOf(+start.value.split("-")[0]),
months.value.indexOf(+start.value.split("-")[1]),
days.value.indexOf(+start.value.split("-")[2])
];
} else {
console.log(year.value, month.value, day.value);
start.value = `${year.value}-${month.value}-${day.value}`;
}
} else if (type == "end") {
if (end.value) {
valueIndex.value = [
years.value.indexOf(+end.value.split("-")[0]),
months.value.indexOf(+end.value.split("-")[1]),
days.value.indexOf(+end.value.split("-")[2])
];
console.log(valueIndex.value, "?????valueIndex.value");
} else {
end.value = `${year.value}-${month.value}-${day.value}`;
}
}
emit("changeData",start.value,end.value);
};
const bindChange = e => {
valueIndex.value = e.detail.value; // 注意这行一定要加上,否则判断的两个索引的值永远不会相等
const val = e.detail.value;
year.value = years.value[val[0]];
month.value = months.value[val[1]];
day.value = days.value[val[2]];
if (dataType.value == "start") {
start.value = `${year.value}-${month.value}-${day.value}`;
} else if (dataType.value == "end") {
end.value = `${year.value}-${month.value}-${day.value}`;
}
getDay();
};
//日期时间
const date = new Date();
const years = ref([]);
const months = ref([]);
const days = ref([]);
const year = ref([]);
const month = ref([]);
const day = ref([]);
const valueIndex = ref([]);
const indicatorStyle = ref(`height: 50px;`);
//获取当前年月日
year.value = date.getFullYear();
month.value = date.getMonth() + 1;
day.value = date.getDate();
for (let i = 1990; i <= date.getFullYear(); i++) {
years.value.push(i);
}
for (let i = 1; i <= 12; i++) {
months.value.push(i);
}
//定义每月的天数,不定义渲染会出问题
for (let i = 1; i <= 31; i++) {
days.value.push(i);
}
//定义每月的天数
const getDay = () => {
let dayNum = 31;
switch (month.value) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
break;
case 4:
case 6:
case 9:
case 11:
dayNum = 30;
break;
case 2:
if (
(year.value % 4 == 0 && year.value % 100 != 0) ||
year.value % 400 == 0
) {
dayNum = 29;
} else {
dayNum = 28;
}
break;
}
days.value = [];
for (let i = 1; i <= dayNum; i++) {
days.value.push(i);
}
};
</script>
<style lang='scss' scoped>
.header {
display: flex;
justify-content: space-between;
align-items: center;
.data {
width: 315rpx;
height: 72rpx;
background: #f6f7f8;
font-family: PingFang SC-Regular;
font-size: 28rpx;
color: #7a7f88;
line-height: 72rpx;
text-align: center;
}
.choose {
}
.heng {
width: 24rpx;
height: 2rpx;
background: #c9cdd4;
}
}
//选择器样式
.picker-box {
width: 100%;
height: 240rpx;
overflow: hidden;
}
::v-deep .indicatorClass {
width: 100%;
height: 80rpx !important;
line-height: 80rpx;
background: #eaf7f3;
z-index: 0; //避免文字被覆盖;
}
.picker-view {
width: 100%;
height: 360rpx;
margin-top: 20rpx;
}
.item {
height: 80rpx;
line-height: 80rpx;
text-align: center;
font-size: 32rpx;
}
.choose {
}
//给中间选中行添加border-radius
::v-deep .view-column.third .indicatorClass {
border-radius: 0 8rpx 8rpx 0;
}
::v-deep .view-column.first .indicatorClass {
border-radius: 8rpx 0 0 8rpx;
}
// 修改原有的上下边框颜色
::v-deep .indicatorClass::after {
border-bottom: 0rpx solid #fff;
}
::v-deep .indicatorClass::before {
border-top: 0rpx solid #fff;
}
//设置蒙层样式
::v-deep .mask-class {
// background: #000;
background-image: linear-gradient(
rgba(255, 255, 255, 0.8),
rgba(255, 255, 255, 0)
),
// linear-gradient(rgba(255, 0, 0, 0.6), rgba(255, 255, 255, 0));
}
</style>
使用:
<my-time :open="openTime" v-if="openTime" @sub="subTime" :timeData="timeData" @close="closeTime"/>
