fullcalendar在vue中的使用 您所在的位置:网站首页 vue-fullcalendar显示二十四节气 fullcalendar在vue中的使用

fullcalendar在vue中的使用

2023-04-21 19:27| 来源: 网络整理| 查看: 265

最近公司刚好有一个日历的需求,选择了Fullcalendar这个插件进行开发,开发过程中,发现网上关于fullcalendar插件在vue中的使用分享并不多,于是就顺便总结了一篇关于vue中使用fullcalendar的文章,希望对小伙伴有帮助。

不想看文字的,可以直接去看源代码,项目地址:github.com/littlePig-z…

这个是Fullcalendar的例子,开发过程中一个很好参考的demo,不局限于vue写法、jQ的写法,有需要的小伙伴可以去看看。

codesandbox.io/search?refi…

那我们现在开始~

一、首先安装fullcalendar的依赖包,fullcalendar.io/docs/plugin… 这个地址是插件合集。

红框部分是比较常用的插件,可自行去查看插件对应的视图,方便使用。

插件合集.png

@fullcalendar/interaction 这个插件主要是用户事件的拖拽交互。 @fullcalendar/list 通常日历是栅格化的日历格子显示,使用这个插件就是把日历用列表的形式显示。视图显示如下图:

列表形式.png

yarn add --save @fullcalendar/daygrid // 日历格子显示 yarn add --save @fullcalendar/list // 列表显示视图用 yarn add --save @fullcalendar/timegrid // 日历时间线视图 yarn add --save @fullcalendar/interaction // 拖拽插件 复制代码 二、安装完依赖插件, 下面是编写自定义头部、引入fullcalendar插件

自定义日历头部.png

需要使用自定义头部的场景:如果需要在头部增加一些自定义下拉选择框,输入框,查询框的情况。官网提供的头部Toolbar中只有一个customButtons属性可自定义,但只能自定义按钮的文本,无法插入html元素。

官网默认的头部,这边就不再重复说了,官网随便找一个例子,都可以找到哈~

这个是Fullcalendar的api合集,方便使用、查找。

下面贴代码:

月 周 今天 上一个 {{ title }} 下一个 查询 {{ arg.event.title }} 更多 {{ arg.timeText }} {{ arg.event.title }} {{ arg.event.title }} 复制代码

写完了html的部分,下面写对应的methods方法,主要是通过getApi()获取到Fullcalendar的实例,调用changeView方法实现视图的切换。

可选的值: 除了dayGridMonth、dayGridWeek、timeGridWeek、resourceTimeline 等等,还可以自定义views 复制代码 import FullCalendar from '@fullcalendar/vue'; import dayGridPlugin from '@fullcalendar/daygrid'; import timeGridPlugin from '@fullcalendar/timegrid'; import listPlugin from '@fullcalendar/list'; import interactionPlugin from '@fullcalendar/interaction'; export default { components: { FullCalendar, // make the tag available }, data() { return { title: '', calendarOptions: { locale: 'zh', plugins: [dayGridPlugin, timeGridPlugin, listPlugin, interactionPlugin], initialView: 'dayGridMonth', editable: true, dayMaxEvents: true, // allow "more" link when too many events eventDurationEditable: true, // 可以调整事件的时间 selectable: true, // 日历格子可选择 nowIndicator: true, // 当前的时间线显示 eventDisplay: 'block', // 争对全天的情况下,以块状显示 headerToolbar: false, // 隐藏头部的导航栏 selectMirror: false, displayEventEnd: true, // like 08:00 - 13:00 eventTimeFormat: { // like '14:30:00' hour: '2-digit', minute: '2-digit', meridiem: false, hour12: false, // 设置时间为24小时 }, slotLabelFormat: { // 左侧时间格式 hour: '2-digit', minute: '2-digit', meridiem: 'lowercase', hour12: false, // false设置时间为24小时 }, events: [ { id: 1, title: 'event 1', start: '2021-10-21', color: 'purple', }, { id: 2, title: 'event 2', start: '2021-10-22', color: 'purple', }, { title: 'event 3', start: '2021-10-23' }, { title: 'event 4', start: '2021-10-24' }, { title: 'event 5', start: '2021-10-21' }, { title: 'event 6', start: '2021-10-21', color: 'purple' }, { title: 'event 7', start: '2021-10-21' }, { id: 3, title: 'event 6', start: '2021-11-21', end: '2021-11-23', color: 'purple', extendedProps: { description: 'asdasdasdasdasdasdasdasds', }, allDay: false, }, { id: 4, title: 'event 7', start: '2021-11-21', extendedProps: { description: '444444444444', }, }, ], eventColor: '#378006', // 事件的颜色 allDayText: '全天', droppable: true, // this allows things to be dropped onto the calendar }, calendarApi: null, monthEvent: [ { id: 'number_1', resourceId: 'number_1', title: 'event 1', start: '2021-10-21', color: 'purple', }, { resourceId: 'number_2', id: 'number_2', title: 'event 2', start: '2021-10-22', color: 'purple', }, { title: 'event 3', start: '2021-10-23' }, { title: 'event 4', start: '2021-10-24' }, { title: 'event 5', start: '2021-10-21' }, { title: 'event 6', start: '2021-10-21', color: 'purple' }, { title: 'event 7', start: '2021-10-21' }, { id: 'number_3', resourceId: 'number_3', title: 'event 6', start: '2021-11-21', end: '2021-11-21', color: 'purple', extendedProps: { description: 'asdasdasdasdasdasdasdasds', } }, { id: 4, title: 'event 7', start: '2021-11-22', extendedProps: { description: '444444444444', }, }, ], weekEvent: [ { id: 'number_1', resourceId: 'number_1', title: 'week_event', start: '2021-11-11', color: 'purple', }, ] }; }, mounted() { this.calendarApi = this.$refs.fullCalendar.getApi(); this.title = this.calendarApi.view?.title; // 模拟动态获取数据 this.getDtata(); }, watch: { // 切换视图显示不同的事件 'calendarApi.view.type'() { this.getDtata() } }, methods: { getDtata() { setTimeout(() => { this.calendarOptions.events = this.calendarApi.view?.type === 'dayGridMonth' ? this.monthEvent : this.weekEvent }, 200); }, prev() { this.calendarApi.prev(); this.title = this.calendarApi.view?.title; }, next() { this.calendarApi.next(); this.title = this.calendarApi.view?.title; }, today() { this.calendarApi.today(); this.title = this.calendarApi.view?.title; }, month() { this.calendarApi.changeView('dayGridMonth'); this.calendarApi.today(); this.title = this.calendarApi.view?.title; }, week() { this.calendarApi.changeView('timeGridWeek'); this.calendarApi.today(); this.title = this.calendarApi.view?.title; }, day() { this.calendarApi.today(); this.title = this.calendarApi.view?.title; }, search() { this.calendarApi.changeView('dayGrid', { start: '2021-10-21', end: '2021-10-23', }); }, }, }; 复制代码 三、功能点实例

自定义头部大概已经实现了,那么接下来开始写咱们的功能啦。

功能点一: 日历的单击、双击功能、

直接在calendarOptions对象中使用方法属性dateClick, 通过定时器来判断是否双击还是单击事件。

let clickCount = 0; let prev = ''; // 上一次点击的dom节点 data() { return { calendarOptions: { ... dateClick: this.handleEventClick, } } } methods: { ...... handleEventClick() { if (e.dateStr !== prev) { clickCount = 0; } clickCount += 1; prev = e.dateStr; setTimeout(() => { if (clickCount === 2) { console.log('db click'); } else if (clickCount === 1) { console.log('one click'); } clickCount = 0; }, 300) }, } 复制代码

功能点二:移到事件上显示弹框并操作

官网有提供两个方法,一个是tooltip(图一), 一个是popover(图二)。

图一.png

图二.png

官网提供的方法以原生js为主的,这边主要以vue的方式来实现。就是通过官网提供的slot:eventContent。当然也可以自行写一个。这边提供两种思路。

更推荐思路一:通过插槽slot的方式去写

结合element-ui组件,方便实现popover功能。

{{ arg.event.title }} 更多 {{ arg.timeText }} {{ arg.event.title }} {{ arg.event.title }} //此处只显示新增的部分 export default { methods: { handleMore() {}, } } 复制代码

思路二:自己写,监听鼠标事件,通过定位的方式实现。这个仅供参考思路哈~

{{ currentView && currentView.title }} 更多配置 {{ arg.timeText }} {{ arg.event.title }} let timer = null; export default { data() { return { currentView: {}, calendarOptions: { .... eventMouseEnter: this.eventMouseEnter, eventMouseLeave: this.handleMouseOut, } } }, methods: { // 事件的鼠标hover事件 eventMouseEnter(e) { const pos = e?.jsEvent; const { popper } = this.$refs; popper.style.display = 'block'; popper.style.left = `${pos.x - popper.offsetWidth / 2}px`; popper.style.top = `${pos.y - popper.offsetHeight}px`; this.currentView = { title: e.event.title, id: e.event.id, }; }, // 弹窗的鼠标hover事件 handleMousover(e) { clearTimeout(timer); const { popper } = this.$refs; popper.style.display = 'block'; }, // 弹窗的鼠标out事件 handleMouseOut() { timer = setTimeout(() => { const { popper } = this.$refs; popper.style.display = 'none'; this.currentView = {}; }, 0); }, // 更多配置操作 handleMore() { console.log(this.currentView.id, '==================='); }, } } .popper { position: fixed; width: 200px; height: 140px; padding: 20px; border: 1px solid #eee; text-align: center; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1); z-index: 1000; display: none; background-color: rgb(188, 236, 250); } 复制代码

功能点3:新增事件

通过点击按钮,实现在日历中动态增加事件。

两种方法(看个人喜好选择): 一、 使用官方提供的方法 addEvent 二、利用vue的双向数据绑定,直接改变calendarOptions里面的event属性

月 周 今天 {{ title }} 新增 查询 methods: { // 在日历中增加事件,大伙可以根据需求去增加自定义时间的事件,我这边是写死一个日期的事件用来示范。 addEvent() { // 第一种思路: 使用官方提供的方法 // this.calendarApi.addEvent({ // title: 'event 11', // start: '2021-11-28', //}) //第二种:通过vue的双向绑定 this.calendarOptions.events.push({ title: 'event 11', start: '2021-11-28', }); }, } 复制代码

功能点四:修改周视图上面的日期

默认显示的格式是 星期一 11/19, 需要自定义的话,可以在views属性中自定义周试图来实现不同格式的时间。类似月视图也是类似的方法。

views: { customeGridWeek: { type: 'timeGridWeek', dayHeaderFormat: { weekday: 'long', }, }, }, //当然也可以直接在calendarOptions属性设置 dayHeaderFormat: { weekday: 'long', }, 但这个就是争对全部视图了,如果只是争对周试图进行修改的话,建议自定义修改周视图 复制代码

视图如下:

周视图.png

下面顺便分享一下 resourceTimeLine 的时间线展示,我刚开始搞的时候,一直显示不出来对应的日历。报没有安装相应的插件的错误,但其实已经引入了对应的插件。去网上搜也没有搜到对应的解决方法。

然后对比网上可以正常使用同学的依赖包版本,我就直接把我的版本绑定到对应的 5.5.0。然后重新安装依赖,神奇般的就可以正常显示了,所以不清楚最新版是不是做了某些改动,需要额外配置什么东西。目前不知道为啥最新版无法正常显示。知道的小伙伴可以评论告知我一下哈~

resourceTimeLine

我们要在自定义头部的地方增加一个下拉选择,手动切换对应的 resourceTimeLine 视图。

主要是分享三个点: 1、修改视图上面的时间线格式(自定义views,然后自由结合这些属性 slotLabelFormat、duration、dayHeaderFormat、slotDuration) 2、左侧的resource自定义显示,这个属性resourceLabelContent 3、动态增加resourceTimeline事件。

争对配置日历时间线格式的,最好不要全局设置,除非你想全部视图的时间线显示是一样的。最好的方式是通过自定义views, 分别设置时间线格式。

周时间线.png

月 周 今天 {{ title }} 新增 查询 //需增加的插件 import resourceTimelinePlugin from '@fullcalendar/resource-timeline'; export default { components: { FullCalendar, // make the tag available }, data() { title: '', currentView: {}, options: [ { value: 'timeline', label: 'resource-timeline' }, { value: 'dategrid', label: 'agenda' }, ], type: 'dategrid', calendarOptions: { locale: 'zh', timeZone: "UTC", plugins: [dayGridPlugin, timeGridPlugin, listPlugin, resourceTimelinePlugin, interactionPlugin], initialView: 'dayGridMonth', resourceAreaWidth: 200, contentHeight: 600, slotMinWidth: 70, resourceOrder: 'number', editable: true, dayMaxEvents: true, // allow "more" link when too many events eventDurationEditable: true, // 可以调整事件的时间 selectable: true, // 日历格子可选择 nowIndicator: true, // 现在的时间线显示 eventDisplay: 'block', // 争对全天的情况下,以块状显示 headerToolbar: false, // 隐藏头部的导航栏 selectMirror: false, displayEventEnd: true, // like 08:00 - 13:00 eventTimeFormat: { // like '14:30:00' hour: '2-digit', minute: '2-digit', meridiem: false, hour12: false, // 设置时间为24小时 }, slotLabelFormat: { // 左侧时间格式 hour: '2-digit', minute: '2-digit', meridiem: 'lowercase', hour12: false, // false设置时间为24小时 }, events: [], eventColor: '#378006', allDayText: '全天', dateClick: this.handleDateClick, resourceAreaHeaderContent: "Rooms", // 左侧resource的header显示文本,默认是resources resources: [ // 对应左侧resource的数据,几条就代表几行 { id: 'number_1', title: 'asas', number: 1 }, { id: 'number_2', title: 'asas', number: 2 }, { id: 'number_3', title: 'asas', number: 3 }, ], schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source', // 目前我也不清楚为啥需要这个凭证,值是从官网粘贴过来的 resourceLabelContent(arg) { // 自定义左侧resource值的显示 return { html: `id: ${arg.resource.id}title: ${arg.resource.title}` } }, views: { // 自定义 resourceTimeLine的 时间显示 customTimeLineWeek: { type: 'resourceTimeline', duration: { weeks: 1 }, slotDuration: { days: 1 }, buttonText: 'Custom Week', slotLabelFormat: { weekday: 'long', // month: 'numeric', // day: 'numeric', omitCommas: true, }, }, customTimeLineMonth: { type: 'resourceTimeline', duration: { month: 1 }, slotLabelFormat: { // month: 'numeric', day: 'numeric', // omitCommas: true, }, }, customGridWeek: { type: 'timeGridWeek', dayHeaderFormat: { weekday: 'long', }, slotLabelFormat: { // 左侧时间格式 hour: '2-digit', minute: '2-digit', meridiem: 'lowercase', hour12: false, // false设置时间为24小时 }, }, }, // 切换视图调用的方法 datesSet(arg) {}, }, calendarApi: null, monthEvent: [ { id: 'number_1', resourceId: 'number_1', title: 'event 1', start: '2021-10-21', color: 'purple', }, { resourceId: 'number_2', id: 'number_2', title: 'event 2', start: '2021-10-22', color: 'purple', }, { title: 'event 3', start: '2021-10-23' }, { title: 'event 4', start: '2021-10-24' }, { title: 'event 5', start: '2021-10-21' }, { title: 'event 6', start: '2021-10-21', color: 'purple' }, { title: 'event 7', start: '2021-10-21' }, { id: 'number_3', resourceId: 'number_3', title: 'event 6', start: '20211120', end: '20211122', color: 'purple', extendedProps: { description: 'asdasdasdasdasdasdasdasds', }, }, { id: 4, title: 'event 7', start: '2021-11-22', extendedProps: { description: '444444444444', }, }, ], weekEvent: [ { id: 'number_1', resourceId: 'number_1', title: 'week_event', start: '2021-11-11', color: 'purple', }, ], }, methods: { getDtata() { setTimeout(() => { this.calendarOptions.events = this.calendarApi.view?.type === 'dayGridMonth' ? this.monthEvent : this.weekEvent; }, 200); }, more() {}, // 增加事件 addEvent() { this.calendarOptions.events.push({ id: 'number_4', resourceId: 'number_3', // 如果是resourceTimeLine视图的话,增加事件时,这个resourceId一定要加上,对应的值为 你要在哪个resource里面加事件,就是用哪个resource的对应id. 通过这个resourceId 去将当前事件绑定到上面。不加这个属性的话,是不会显示出来的。 title: 'event 11', start: '2021-11-28', }); }, // 单击事件 handleDateClick(e) { if (e.dateStr !== prev) { clickCount = 0; } clickCount += 1; prev = e.dateStr; setTimeout(() => { if (clickCount === 2) { console.log('db click'); } else if (clickCount === 1) { console.log('one click'); } clickCount = 0; }, 300); }, prev() { this.calendarApi.prev(); this.title = this.calendarApi.view?.title; }, next() { this.calendarApi.next(); this.title = this.calendarApi.view?.title; }, today() { this.calendarApi.today(); this.title = this.calendarApi.view?.title; }, month() { if (this.type === 'timeline') { this.calendarApi.changeView('customTimeLineMonth'); }else { this.calendarApi.changeView('dayGridMonth'); } this.calendarApi.today(); this.title = this.calendarApi.view?.title; }, week() { if (this.type === 'timeline') { this.calendarApi.changeView('customTimeLineMonth'); }else { this.calendarApi.changeView('customGridWeek'); } this.calendarApi.today(); this.title = this.calendarApi.view?.title; }, day() { this.calendarApi.today(); this.title = this.calendarApi.view?.title; }, search() { this.calendarApi.changeView('dayGrid', { start: '2021-10-21', end: '2021-10-23', }); }, // 下拉框选择的change事件 handleType() { if(this.type ==='timeline') { this.calendarApi.changeView('customTimeLineMonth') this.calendarOptions.slotLabelFormat = null // 设置null 是因为我们全局设置了 slotLabelFormat的属性,是针对dayGrid视图的,不适用于timeline视图。 } else { this.calendarApi.changeView('dayGridMonth') } }, } } 复制代码

需要注意的点:

为啥增加了事件没有正常显示在视图上?

在resourceTimeLine的视图下,定义事件、增加事件的时候,事件对象务必要增加一个属性 resourceId,对应的值为 你要在哪个resource里面加事件,就是用哪个resource的对应id. 通过这个resourceId 去将当前事件绑定到上面。

分享的内容就这么多啦,希望可以帮助到有需要的小伙伴。如有不正确的地方,不懂的地方欢迎评论。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有