以下是 Element UI 的 el-calendar 组件实现点击事件、高度调整及自定义内容的完整方案,结合官方网页与最佳实践整理:
一、点击事件设置
1. 基础点击事件绑定
通过 date-cell 插槽自定义日期单元格,绑定 @click 事件:
<template>
<el-calendar>
<template #date-cell="{ date, data }">
<div
class="custom-date-cell"
@click="handleDateClick(data.day)"
>
{{ data.day.split("-").slice(2).join("-") }}
<span v-if="isHoliday(data.day)" class="holiday-tag">休</span>
</div>
</template>
</el-calendar>
</template>
<script>
export default {
methods: {
handleDateClick(date) {
this.$alert(`点击日期:${date}`, '提示');
},
isHoliday(date) {
// 节假日判断逻辑(示例)
return date === '2025-06-01';
}
}
}
</script>
关键点:
- 使用
date-cell插槽覆盖默认日期单元格 - 通过
data.day获取完整日期(格式yyyy-MM-dd) - 点击事件绑定到外层
div防止穿透问题
2. 跨月份按钮事件
监听日历切换按钮点击:
mounted() {
this.$nextTick(() => {
// 上个月按钮
document.querySelector('.el-calendar__button-group .el-button:nth-child(1)')
.addEventListener('click', this.handlePrevMonth)
// 下个月按钮
document.querySelector('.el-calendar__button-group .el-button:nth-child(3)')
.addEventListener('click', this.handleNextMonth)
})
}
二、高度设置方案
1. 固定高度
通过 CSS 覆盖默认样式:
<style scoped>
/deep/ .el-calendar {
height: 500px; /* 整体高度 */
.el-calendar__body {
height: calc(100% - 50px); /* 减去标题栏高度 */
}
.el-calendar-table {
height: 100%;
.el-calendar-day {
height: 60px; /* 单元格高度 */
line-height: 60px;
}
}
}
</style>
注意:使用 /deep/ 或 ::v-deep 穿透作用域样式
2. 自适应高度
<template>
<div class="calendar-container">
<el-calendar style="height: 100%"></el-calendar>
</div>
</template>
<style>
.calendar-container {
height: 60vh; /* 视口高度60% */
display: flex;
flex-direction: column;
}
</style>
三、自定义内部内容
1. 基础内容覆盖
<template>
<el-calendar>
<template #date-cell="{ date, data }">
<div class="fancy-date">
<div class="day-number">
{{ data.day.split("-").slice(2).join("-") }}
</div>
<div class="event-indicator" v-if="hasEvent(data.day)">
<i class="el-icon-bell"></i>
</div>
</div>
</template>
</el-calendar>
</template>
2. 复杂布局示例
<template>
<el-calendar>
<template #date-cell="{ date, data }">
<div class="custom-cell">
<div class="top-row">
<span>{{ data.weekday }}</span>
<span>{{ data.day.split("-").slice(2).join("-") }}</span>
</div>
<div class="bottom-row">
<el-tag
v-for="(event, index) in getEvents(data.day)"
:key="index"
size="mini"
type="info"
>
{{ event.title }}
</el-tag>
</div>
</div>
</template>
</el-calendar>
</template>
<script>
export default {
methods: {
getEvents(date) {
// 模拟从接口获取事件数据
return [{
title: '会议',
time: '14:00'
}]
}
}
}
</script>
<style scoped>
.custom-cell {
position: relative;
height: 100%;
padding: 5px;
}
.top-row {
display: flex;
justify-content: space-between;
margin-bottom: 3px;
}
.bottom-row {
display: flex;
flex-wrap: wrap;
gap: 2px;
}
</style>
四、高级功能实现
1. 日期禁用
通过 disabled-date 属性:
<el-calendar
:disabled-date="disabledDate"
>
<!-- 插槽内容 -->
</el-calendar>
<script>
export default {
methods: {
disabledDate(date) {
// 禁用今天之前的日期
return date < new Date()
}
}
}
</script>
2. 动态内容加载
<template>
<el-calendar>
<template #date-cell="{ date, data }">
<div @click="loadData(date)">
<div>{{ data.day.split("-").slice(2).join("-") }}</div>
<div v-if="loadingDate === data.day">加载中...</div>
<div v-else>{{ eventCount[data.day] || 0 }} 个事件</div>
</div>
</template>
</el-calendar>
</template>
<script>
export default {
data() {
return {
eventCount: {},
loadingDate: null
}
},
methods: {
async loadData(date) {
this.loadingDate = date
const res = await fetch(`/api/events?date=${date}`)
this.eventCount[date] = res.data.count
this.loadingDate = null
}
}
}
</script>
五、样式优化技巧
- 主题色修改:
/deep/ .el-calendar-day.is-selected {
background: #409EFF !important;
color: #fff !important;
}
- 悬停效果:
/deep/ .el-calendar-day:hover {
background: rgba(64, 158, 255, 0.1) !important;
}
- 非本月日期样式:
/deep/ .el-calendar-day.prev,
/deep/ .el-calendar-day.next {
color: #C0C4CC !important;
}
六、注意事项
- 作用域插槽:确保使用
scoped样式时正确穿透组件层级 - 性能优化:大数据量时使用虚拟滚动
- 移动端适配:添加
@media查询调整单元格尺寸 - 事件冒泡:阻止事件穿透到父容器
通过上述方案,可实现高度定制化的日历组件,满足企业级应用需求。具体实现需根据业务场景调整细节。