el-data-picker日期选择器
我们先看最终实现的效果图
下面是代码:
<template>
<div id="box">
<el-date-picker popper-class="data-style" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" :picker-options="pickerOptions" :inline="true">
<template #default="{ date }">
<div class="date-wrapper">
<div :class="getCustomClass(date)">
{{ date.getDate() }}
<span v-if="highlightedDates.includes(formatDate(date))" class="red-dot">已租出</span>
</div>
</div>
</template>
</el-date-picker>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ElDatePicker } from 'element-plus'
// const selectedDate = ref('')
const highlightedDates = ['2023-09-16', '2023-10-23', '2023-10-24', '2023-10-27', '2023-10-26', '2023-10-29', '2023-11-01', '2023-12-24', '2023-11-02', '2023-11-03', '2023-11-05', '2023-11-23']
const pickerOptions = {
disabledDate: (time) => {
const date = new Date(time)
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
return highlightedDates.indexOf(`${year}-${month}-${day}`) === -1
},
}
function formatDate(date) {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
}
function getCustomClass(date) {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const formattedDate = `${year}-${month}-${day}`
if (highlightedDates.includes(formattedDate)) {
return 'red-date'
}
return ''
}
</script>
<!-- 因为日历组件还没有显示出来,所以我们无法通过深度监听来拿到日历弹层就需要另外写一个style样式表,没有样式隔离 -->
<style lang="scss">
.data-style {
// border: 1px solid red !important;
// display: block !important;
// 动态修改日历弹层的样式(不需要样式渗透)(如果不生效,记得添加 !important)
}
</style>
<style lang="scss" scoped>
.date-wrapper {
position: relative;
}
.red-date {
display: inline-block;
border-radius: 50%;
width: 20px;
height: 20px;
line-height: 20px;
background-color: red;
color: white;
position: relative;
}
.red-dot {
position: absolute;
bottom: -18px;
left: -4px;
width: 100%;
font-size: 10px;
color: red;
text-align: center;
white-space: nowrap;
}
</style>
注意:
因为日历组件还没有显示出来,所以我们无法通过深度监听来拿到日历弹层就需要另外写一个style样式表,没有样式隔离
对上面的代码进行解释:
当用户浏览某个日期选择器时,该代码会为其提供一些特殊功能。下面是代码的详细解释:
-
首先,我们定义了一个数组变量
highlightedDates,其中包含一些已被选中的日期,这些日期将在日期选择器中以特殊方式标记。用户可以根据这些标记来选择可用日期。 -
接下来,我们创建了一个对象变量
pickerOptions,其中包含了一个disabledDate函数。这个函数用于禁用未被选中的日期,以确保用户不能选择已被租出的日期。pickerOptions对象将作为选项传递给日期选择器组件。 -
在
disabledDate函数中,我们先获取了即将被渲染的日期date。然后,我们使用highlightedDates数组来检查该日期是否存在于已被选中的日期中。如果存在,则返回true,表示该日期被禁用,用户不能选择它。 -
最后,我们定义了一个
getCustomClass函数。这个函数在渲染日期时被调用,用于决定日期的样式类。在本例中,我们根据日期是否在highlightedDates数组中来切换样式类。如果日期在数组中,我们将其样式类设置为red-date,这样它将以特殊的红色样式显示。
为了增强代码的可读性和可维护性,我们还可以添加一些样式表。其中包含了一些定义 red-date 样式的规则,以及一些用于修改日期选择器样式的规则。这些样式表将确保日期选择器和标记样式的正确显示。
综上所述,这段代码利用 Element Plus 库的日期选择器组件,实现了以下功能:
- 标记已经被选中的日期
- 禁用已经被选中的日期,确保用户不能选择它们
- 改变已选中日期的样式,以突出显示这些日期
el-calendar日历
我们先看最终实现的效果图
下面是代码
<template>
<div>
<el-calendar :value="selectedDate" :first-day-of-week="1">
<template #date-cell="{ data }">
<div class="day" :class="{ 'is-highlighted': checkIfDateHasReminder(data) }">
<div class="day-number">{{ data.day.split('-')[2] }}</div>
<div class="reminder" v-if="checkIfDateHasReminder(data)">已租出</div>
</div>
</template>
</el-calendar>
</div>
</template>
<script setup>
import { ref } from 'vue'
const selectedDate = ref()
// 下面是我模拟的需要标注的日期,开发过程中可以将这个数据替换请求回来的数据
const highlightedDates = ['2023-09-16', '2023-10-23', '2023-10-24', '2023-10-27', '2023-10-26', '2023-10-29', '2023-11-01', '2023-12-24', '2023-11-02', '2023-11-03', '2023-11-05', '2023-11-23']
// 判断日期是否是我们需要标注的日期
const checkIfDateHasReminder = (data) => {
if (highlightedDates.includes(data.day)) {
return true
}
return false
}
</script>
<style lang="scss" scoped>
:deep(.el-calendar) {
width: 648px;
height: 404px;
}
:deep(.el-calendar-table .el-calendar-day) {
width: 60px;
height: 60px;
margin-left: 12px;
}
:deep(.el-calendar-day) {
border: none;
}
:deep(.el-calendar__week) {
border: none;
}
:deep(.el-calendar__date) {
border: none;
}
:deep(.el-calendar__date:last-child) {
border: none;
}
.day {
text-align: center;
.reminder {
font-size: 12px;
}
}
.day-number {
margin-bottom: 5px;
}
.is-highlighted {
color: red;
}
</style>
对上面的代码进行解释:
这段代码是一个使用 Vue.js 和 Element Plus 组件库实现的日期选择器组件。以下是对代码的详细解释:
- 在组件定义的 template 标签中,创建了一个名为
el-calendar的 Element Plusel-calendar组件。该组件绑定了一个响应式变量selectedDate以实现日期选中的双向绑定,同时设置了每周的第一天是星期一。 - 在组件模板内部,使用了 Element Plus 提供的插槽
date-cell,用来定义一个自定义日期单元格的展示方式。 - 在
date-cell插槽中,通过获取data参数来获取日期数据,用于决定是否需要对该日期进行标注。 - 使用开发者自定义的方法
checkIfDateHasReminder对当前日期进行判断。如果该日期的 day 值在highlightedDates数组中存在,则添加is-highlighted类名,表示该日期需要被标注。同时判断是否需要显示 “已租出” 提示,如果需要,就在单元格中进行展示。 - 在组件中使用了嵌套的 div 元素,用来展示日期和
已租出提示文字。 - 在组件的 script setup 标签中,使用了 Vue 的 ref 函数创建了一个响应式变量
selectedDate,并设置为默认空值。 - 创建了一个名为
highlightedDates的数组,模拟了需要标注的日期数据。 - 创建了一个名为
checkIfDateHasReminder的自定义方法,用来判断当前日期是否需要被标注。 - 在样式中使用了名为
:deep的伪类选择器,用来穿透组件的作用域,设置了组件整体和日期单元格的外观样式。
注意
- 这里我们使用了element-plus中提供的插槽来获取到数据
#date-cell="{ data }"这个data的结构是这样的。如果想要自定义结构,可以自己选择使用的属性。
- 上面的代码中的
highlightedDates是我模拟的数据,在真实开发中,大家可以请求接口,拿回来数据 {{ data.day.split('-')[2] }}这个位置是为了让日历显示日期而不显示年份。