日历组件
注意
日历组件我在这里用的就是Fullcalendar
个人觉得他是前端最强的日历组件,没有之一
基本使用
安装
- Vue2
js
npm install --save @fullcalendar/vue
//下面包是日历的周视图、日视图等插件包:
npm install --save @fullcalendar/core @fullcalendar/daygrid @fullcalendar/interaction @fullcalendar/list @fullcalendar/timegrid
//安装后的fullcalendar源码和其它插件都会在@fullcalendar
npm install --save dayjs
//安装dayjs用于格式化时间格式- Vue3
bash
npm install --save @fullcalendar/vue3
//下面包是日历的周视图、日视图等插件包:
npm install --save @fullcalendar/core @fullcalendar/daygrid @fullcalendar/interaction @fullcalendar/list @fullcalendar/timegrid
//安装后的fullcalendar源码和其它插件都会在@fullcalendar
npm install --save dayjs
//安装dayjs用于格式化时间格式架构
bash
├── src
│ ├── components
│ │ ├── chooseCalendar
│ │ │ ├── lib (引入的第三方库)
│ │ │ │ └── xxx.json
│ │ │ ├── src (源码)
│ │ │ │ ├── index.vue
│ │ │ ├── index.tsindex.ts
ts
import { type App } from "vue";
import chooseCalendar from "./src/index.vue";
// 让这个组件可以通过use的形式使用
export default {
install(app: App) {
app.component("YJ-choose-calendar", chooseCalendar);
},
};interface/chooseCalendar/type.ts
ts
export interface EventItem {
// 事件标题
title: string;
// 开始时间
start: string;
// 结束时间
end: string;
// 是否可拖动编辑
editable?: boolean;
}components/chooseCalendar/src/index.vue
vue
<template>
<div id="calendar"></div>
</template>
<script lang="ts" setup>
// 在vite里面使用fullcalendar 需要引入一个包
// import '@fullcalendar/core/vdom'
import {
Calendar,
type EventClickArg,
type EventContentArg,
} from "@fullcalendar/core";
import daygridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin, {
type DateClickArg,
} from "@fullcalendar/interaction";
import { ref, onMounted, type PropType, watch } from "vue";
import { type EventItem } from "@/interfaces/chooseCalendar/type";
let props = defineProps({
// 日历显示的语言
local: {
type: String,
default: "zh-cn",
},
// 视图模式
initialView: {
type: String,
default: "dayGridMonth",
},
// 按钮文字
buttonText: {
type: Object,
default: () => {
return {
today: "今天",
month: "月",
week: "周",
day: "日",
};
},
},
// 头部工具栏
headerToolbar: {
type: Object,
default: () => {
return {
left: "prev,next, today",
center: "title",
right: "dayGridMonth,timeGridWeek,timeGridDay",
};
},
},
// 底部工具栏
footerToolbar: {
type: Object,
},
// 日历事件
events: {
type: Array as PropType<EventItem[]>,
default: () => [],
},
// 自定义渲染内容方法
eventContent: {
type: Function,
},
});
let emits = defineEmits(["date-click", "event-click"]);
// 日历对象
let calendar = ref<Calendar>();
// 生成日历的方法
let renderCalendar = () => {
let el = document.getElementById("calendar");
if (el) {
// 日历的配置选项
calendar.value = new Calendar(el, {
// 使用到的插件
plugins: [daygridPlugin, interactionPlugin, timeGridPlugin],
// 视图模式
initialView: props.initialView,
// 语言
locale: props.local,
// 按钮文字
buttonText: props.buttonText,
// 头部工具栏
headerToolbar: props.headerToolbar,
// 底部工具栏
footerToolbar: props.footerToolbar,
// 显示周末
weekends: true,
// 事件源
eventSources: [
{
// 生成事件
events(e, callback) {
if (props.events.length) callback(props.events);
else callback([]);
},
},
],
// 点击日历的某一天
dateClick(info: DateClickArg) {
// console.log(info)
emits("date-click", info);
},
// 点击日历上的时间
eventClick(info: EventClickArg) {
// console.log('eventClick', info)
emits("event-click", info);
},
// 显示事件的结束时间
displayEventEnd: true,
// 自定义渲染内容
eventContent: props.eventContent,
// 拖拽合集开始
editable: true, // 启用事件拖拽和调整大小
droppable: true, // 启用外部元素拖拽到日历
eventDrop: function (info) {
console.log("Event dropped: " + info.event.title);
console.log(info);
console.log("开始时间:" + info.event.startStr);
console.log("结束时间:" + info.event.endStr);
console.log("结束时间:" + info.event.title);
},
eventResize: function (info) {
console.log("Event resized: " + info.event.title);
console.log(info);
},
drop: function (info) {
console.log("Dropped");
console.log(info);
console.log(info.view.calendar);
},
// 拖拽合集结束
});
calendar.value.render();
}
};
// 监听事件源的变化
watch(
() => props.events,
() => {
renderCalendar();
},
{ deep: true },
);
onMounted(() => {
renderCalendar();
});
</script>
<style lang="scss" scoped>
svg {
width: 1em;
height: 1em;
}
</style>父元素调用
vue
<template>
<div>
<YJ-choose-calendar
:events="events"
:eventContent="eventContent"
@date-click="dateClick"
></YJ-choose-calendar>
</div>
</template>
<script setup lang="ts">
import { type DateClickArg } from "@fullcalendar/interaction";
import { type EventItem } from "@/interfaces/chooseCalendar/type";
import { ref } from "vue";
import { type EventContentArg } from "@fullcalendar/core";
import dayjs from "dayjs";
let events = ref<EventItem[]>([
{
title: "购物",
start: "2025-02-04 10:00:00",
end: "2025-02-06 12:00:00",
editable: true,
},
{
title: "学习",
start: "2025-02-05 08:00:00",
end: "2025-02-05 16:00:00",
},
]);
let dateClick = (info: DateClickArg) => {
let event = {
start: `${info.dateStr} 12:00:00`,
end: `${info.dateStr} 13:00:00`,
title: "吃饭",
};
events.value.push(event);
console.log(info);
};
let eventContent = (arg: EventContentArg) => {
let el = document.createElement("div");
let start = `${dayjs(arg.event.start).format("YYYY-MM-DD HH:mm:ss")}时开始`;
let end = `${dayjs(arg.event.end).format("YYYY-MM-DD HH:mm:ss")}时结束`;
el.innerHTML = `
<img src="https://jsopy.oss-cn-beijing.aliyuncs.com/IMAGES/avatar.jpg" style="width:20px;height:20px;">
<div>开始时间: ${start}</div>
<div>结束时间: ${end}</div>
<div>标题: ${arg.event.title}</div>
`;
return {
domNodes: [el],
};
};
</script>
<style scoped></style>