Element UI 的 el-calendar 组件实现点击事件、高度调整及自定义内容的完整方案

521 阅读1分钟

以下是 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>

五、样式优化技巧

  1. ​主题色修改​​:
/deep/ .el-calendar-day.is-selected {
  background: #409EFF !important;
  color: #fff !important;
}
  1. ​悬停效果​​:
/deep/ .el-calendar-day:hover {
  background: rgba(64, 158, 255, 0.1) !important;
}
  1. ​非本月日期样式​​:
/deep/ .el-calendar-day.prev,
/deep/ .el-calendar-day.next {
  color: #C0C4CC !important;
}

六、注意事项

  1. ​作用域插槽​​:确保使用 scoped 样式时正确穿透组件层级
  2. ​性能优化​​:大数据量时使用虚拟滚动
  3. ​移动端适配​​:添加 @media 查询调整单元格尺寸
  4. ​事件冒泡​​:阻止事件穿透到父容器

通过上述方案,可实现高度定制化的日历组件,满足企业级应用需求。具体实现需根据业务场景调整细节。