一、自定义日历
目录
先上效果图
一、自定义日历组件
已经封装成vue组件,可选择切换年月:
<template>
<div class="calendar-container">
<div class="year flex items-center">
<el-config-provider :locale="local">
<el-date-picker
v-model="selectDate"
@change="rsetDate"
type="month"
class="testDate"
popper-class="dark_form"
style="width: 1.2rem"
:placeholder="nowDate.year + '-' + (nowDate.month + 1)"
>
</el-date-picker>
</el-config-provider>
<div class="img"></div>
</div>
<ul class="week flex">
<li v-for="(o, index) in 7" :key="o">{{ formatWeek(index) }}</li>
</ul>
<ul class="date">
<li class="none-week dayli" v-for="o in lastMonthDays" :key="o + 50">
{{ lastMonthStartDay + o - 1 }}
</li>
<!-- 当月 -->
<span
@click="clickEvent"
v-for="day in nowMonthDays"
:key="day"
:class="day == nowDate.date ? 'dayli today' : 'dayli'"
>
{{ day }}
</span>
<li
class="none-week dayli"
v-for="day in 42 - lastMonthDays - nowMonthDays"
:key="day + 100"
>
{{ day }}
</li>
</ul>
</div>
</template>
<script>
import zhcn from "element-plus/lib/locale/lang/zh-cn";
// let local = zhcn
export default {
data() {
return {
local: zhcn,
selectDate: [], //选择日期列表
nowDate: this.getDate(new Date()), //当前设置时间 默认为当前系统时间
today: "",
};
},
computed: {
lastMonthDays() {
return this.startWeek();
},
lastMonthStartDay() {
return (
this.calcLastMonthDays(this.nowDate.year, this.nowDate.month) -
(this.startWeek() - 1)
);
},
nowMonthDays() {
return this.calcDays(this.nowDate.year, this.nowDate.month);
},
},
created() {
if (this.setDate) {
this.nowDate = this.getDate(this.setDate);
this.settime(this.nowDate)
}
// var _this=this;
// this.today=this.nowDate.date;
// console.log(this.nowDate)
// console.log(this.today)
},
methods: {
// 传输时间给父组件
settime(){
let arr=[this.nowDate.year+'-'+(this.nowDate.month+1),this.nowDate.date]// [2022-8,4]
this.$emit('settime',arr)
},
//选择月份
rsetDate() {
this.nowDate = this.getDate(this.selectDate);
this.settime(this.nowDate)
},
getDate(date) {
return {
year: date.getFullYear(),
month: date.getMonth(),
day: date.getDay(),
date: date.getDate(),
};
},
formatWeek(day) {
switch (day) {
case 0:
return "日";
case 1:
return "一";
case 2:
return "二";
case 3:
return "三";
case 4:
return "四";
case 5:
return "五";
case 6:
return "六";
}
},
//判断闰年
isLeapYear(year) {
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
},
//根据日子计算星期
calcWeekend(year, month, day) {
return new Date(year, month, day).getDay();
},
//计算某年某月的天数
calcDays(year, month) {
const monthDay = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if (this.isLeapYear(year) && month === 1) return 29;
else return monthDay[month];
},
//计算上个月天数
calcLastMonthDays(year, month) {
if (month === 0) {
return this.calcDays(year - 1, 11);
} else {
return this.calcDays(year, month - 1);
}
},
//计算当月开始星期
startWeek() {
return this.calcWeekend(this.nowDate.year, this.nowDate.month, 1);
},
//
clickEvent(e) {
let monthNo = this.nowDate.month;
let month = monthNo <= 11 ? monthNo + 1 : 0;
let date = {
year: this.nowDate.year,
month: month,
week: new Date(
this.nowDate.year,
this.nowDate.month,
e.target.innerText
).getDay(),
day: Number(e.target.innerText),
};
// this.$emit("click-event", date);
this.nowDate.date=date.day
console.log(date.day);
this.settime(this.nowDate)
},
},
};
</script>
<style lang="scss" scoped>
.calendar-container {
background: rgba(7, 25, 61, 0.39);
border-radius: 4px;
padding: 16px;
}
.year {
position: relative;
::v-deep {
.el-input__wrapper {
border-radius: 4px;
border: 1px solid #818ea9;
box-shadow: none;
margin-bottom: 16px;
}
.el-input__prefix {
width: 33px;
}
}
.img {
position: absolute;
top: 1.5px;
z-index: 888;
width: 33px;
height: 27px;
margin: 2px;
// margin-right: 16px;
background-image: url("~@/assets/imgs/landedEstate/public-resources/time.png");
background-size: 100% 100%;
background-repeat: no-repeat;
}
p {
font-family: "HarmonyOS Sans";
font-style: normal;
font-weight: 400;
font-size: 16px;
line-height: 19px;
color: #ffffff;
margin-right: 12px;
}
}
.week {
padding: 8px;
justify-content: space-between;
align-items: center;
height: 40px;
height: 40px;
background: linear-gradient(
270deg,
rgba(19, 30, 52, 0.308) 0%,
rgba(19, 30, 52, 0.7) 100%
);
border-radius: 4px;
border-radius: 4px;
margin-bottom: 12px;
li {
height: 24px;
width: 32px;
align-items: center;
justify-content: center;
box-sizing: border-box;
display: flex;
flex-wrap: wrap;
list-style: none;
align-content: center;
font-family: "HarmonyOS Sans";
font-style: normal;
font-weight: 400;
font-size: 16px;
line-height: 20px;
text-align: center;
letter-spacing: 0.02em;
}
}
.date {
justify-content: center;
box-sizing: border-box;
display: flex;
flex-wrap: wrap;
list-style: none;
margin-top: 0;
.dayli:nth-child(7n) {
border-radius: 0px 2px 2px 0;
// color: #22ff47;
}
.dayli:nth-child(7n + 1) {
border-radius: 2px 0px 0px 2px;
// color: #22ff47;
}
span {
border-bottom: 1px;
border-top: 1px;
border-color: #818ea9;
border-style: solid;
}
span:last-of-type {
border-radius: 0px 2px 2px 0px;
// color: #22ff47;
border-right: 1px;
border-color: #818ea9;
border-style: solid;
}
span:first-of-type {
border-radius: 0px 2px 2px 0px;
// color: #ff229c;
border-left: 1px;
border-color: #818ea9;
border-style: solid;
}
.today {
background: linear-gradient(
112.08deg,
#8ab1ff 0.45%,
#5985dd 61.64%,
#3f6dcb 95.27%
);
box-shadow: -1px 3px 4px rgba(124, 149, 219, 0.6);
border-radius: 4px;
font-family: "HarmonyOS Sans";
font-style: italic;
font-weight: bolder;
font-size: 16px;
line-height: 20px;
/* identical to box height, or 125% */
text-align: center;
letter-spacing: 0.02em;
color: #ffffff;
text-shadow: 0px 2px 4px #2366e9;
}
li,
span {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 8px;
width: 43px;
height: 35px;
text-align: center;
font-family: "HarmonyOS Sans";
font-style: normal;
font-weight: 400;
font-size: 16px;
line-height: 20px;
text-align: center;
letter-spacing: 0.02em;
color: #ffffff;
background: #131e34b3;
}
li:hover {
background: linear-gradient(
112.08deg,
#8ab1ff 0.45%,
#5985dd 61.64%,
#3f6dcb 95.27%
);
box-shadow: -1px 3px 4px rgba(124, 149, 219, 0.6);
border-radius: 4px;
cursor: pointer;
}
.none-week {
font-family: "HarmonyOS Sans";
font-style: normal;
font-weight: 400;
font-size: 16px;
line-height: 20px;
text-align: center;
letter-spacing: 0.02em;
color: #ffffff;
opacity: 0.4;
}
}
</style>
二、时间选择样式自定义
因 element-UI的时间选择器 el-date-picker 是将元素直接挂载到页面的<body>
中,而非自身元素下,所以使用 /deep/、 >>>、
::v-deep 等穿透无法定位到元素。
解决方案:
利用时间选择器的popper-class
属性,设置样式。
有2种方式:
- 创建style.scss,在该文件里进行样式的编写,再引入
- 在APP.vue中加入样式的编写(根文件)
<el-date-picker
type="month"
popper-class="dark_form" >
</el-date-picker>
//效果图对应样式
// 日期选择弹窗样式
.el-picker__popper.el-popper[role="tooltip"] {
border-color: #24386000;
}
.el-popper.is-light .el-popper__arrow::before {
background: #131e34;
border: none !important;
}
.dark_form {
background: #131e34 !important;
border: #131e34;
.el-date-picker__header--bordered {
border-bottom: solid 0.01rem #818ea9;
}
.el-picker__popper.el-popper[role="tooltip"] .el-popper__arrow::before {
border: none !important;
}
.el-picker-panel__body {
background: #131e34 !important;
}
.el-date-picker__header-label {
color: #fbfbfb;
font-family: "HarmonyOS Sans";
}
.el-picker-panel__icon-btn {
color: #fbfbfb;
font-family: "HarmonyOS Sans";
}
.el-month-table td .cell {
color: #fbfbfb;
font-family: "HarmonyOS Sans";
}
.el-year-table td .cell {
color: #fbfbfb;
font-family: "HarmonyOS Sans";
}
}
搜索
复制