1. 安装和使用
1.1 安装以下npm包
npm install --save @fullcalendar/vue @fullcalendar/core // 核心库
npm install --save @fullcalendar/interaction // 交互库
npm install --save @fullcalendar/moment // 格式化时间库。可以在插件使用YYYY MM
npm install --save @fullcalendar/daygrid // 月视图
1.2 使用
<template>
<FullCalendar
class="fullCalendar"
:options="calendarOptions"
ref="fullCalendar"/>
</template>
<script>
import FullCalendar from '@fullcalendar/vue' // 核心库
import InteractionPlugin from '@fullcalendar/interaction' // 交互库
import MomentPlugin from '@fullcalendar/moment' // 格式化时间库。可以在插件使用YYYY MM
import DaygridPlugin from '@fullcalendar/daygrid' // 月视图
export default {
components: {
FullCalendar
},
data () {
return {
calendarOptions: {
// 默认视图:月视图
initialView: 'dayGridMonth',
// 是否显示周六、周日
weekends: false,
// 引入插件, 如果有多个视图最好都先添加进去。
plugins: [
InteractionPlugin,
MomentPlugin,
DaygridPlugin
]
}
}
}
}
</script>
1.3 需要注意的几点
- 我使用的版本都是5.9.0版本。(每个版本dom结构都会有一点小变化,不是特需最好不要升降版本)
- 不要给FullCalendar组件绑定动态属性或者动态方法。
- 一个页面有多个视图(日、周、月)一定要注意样式冲突问题。每个视图都有单独的class。
- FullCalendar5选项和方法一定要写在options对象中,FullCalendar4选项配置是直接写在组件内的。这和5是最大的区别(dom结构也发生很大变化)。
- 如果想要加载不同视图可以点击插件链接查看
2 API说明
2.1 FullCalendar4与FullCalendar5的API区别
FullCalendar5增加很多API和钩子函数,在修改和增加一些新的功能上比4版本更加方便。能升级到版本5就使用5
例:想要修改和添加月视图每个单元格的文本内容和class可以使用dayCellContent
和dayCellClassNames
2.2 API官网链接
本来想的是根据自己理解把API给翻译翻译,后来发现官网不用科学上网也可以上去。
官网:fullcalendar.io/docs#toc
插件:fullcalendar.io/docs/plugin…
版本5和4之间的差异:fullcalendar.io/docs/upgrad…
3 在项目遇到的一些问题
3.1 视图样式修改问题
插件的样式对于项目而言或多或少都需要进行调整,在一个页面可能会有日、周、月、资源横向图、资源竖向图等。很多元素class名字都相同,只想要修改月视图内容里面的样式而不影响其它视图样式,需要外层不同class进行包裹。
我的做法是把每个视图当作不同模块进行处理,就算有通用样式也不会单独拎出来,这样保证我修改某个视图不会影响其它视图。
如:月视图内容包裹class类 .fc-dayGridMonth-view
.fc-dayGridMonth-view {
// 子元素的内容样式
}
- 月视图:
.fc-dayGridMonth-view
- 周视图:
.fc-timeGridWeek-view
- 日视图:
.fc-timeGridDay-view
- 垂直资源视图:
.fc-resourceTimeGrid-view
- 时间轴视图:
.fc-resourceTimeline-view
标题头所有的视图使用的同一个。
3.2 设置属性
3.2.1 直接赋值
this.calendarOptions.weekends = true
3.2.2 使用API设置
// getApi()是组件里面的方法。
this.$refs.fullCalendar.getAPi().setOption('weekends', true)
3.2.3 在不确定选项添加新的属性
比如选项customButtons
有多个自定义按钮,想要动态新添加一个,可以试试这么做。
// 先获取customButtons值
let customButtonsOption = this.$refs.fullCalendar.getApi().getOption('customButtons');
// 然后再设置
this.$refs.fullCalendar.getApi().setOption('customButtons', {
...customButtonsOption,
newBtn: {}
})
3.3 时间轴视图(resourceTimeline)左右横线对不齐
原因:右侧的滚动条是默认的不好看。所以滚动条是重新设置的样式。
遇到的问题:如果从右侧进行向下滚动,导致左侧的横向线与右侧的横向线对不齐。这是因为左侧并没有出现滚动条,右侧有滚动条,导致高度位置不一致。
解决方法:给左侧列表也设置一样的滚动条高度,如果不想显示滚动条,滚动条透明度为0。
3.4 设置垂直资源视图(resourceTimeGridDay)左侧时间宽度
/* 可以进行这么设置 找到col标签 */
.fc-scrollgrid > colgroup > col {
min-width: 92px !important;
}
3.5 nowIndicatorContent(当前时间指示器)不触发
这个BUG目前我只是在resourceTimeline
这个视图发现过。
功能:每分钟更新都会触发该回调。
问题:设置nowIndicatorContent
回调并没有实时触发。
设置:如果是resourceTimeline
视图设置slotDuration
或slotLabelInterval
为1小时以上(包括一小时)就不会触发该回调函数。
解决方案:可以自己写一个分钟更新就调用的方法。注意:它不是每过一分钟就触发,假设当前时间为16:10:30。过了30秒到16:11:00。那么这个方法就该触发。
4. 我的配置选项
calendarOptions: {
nowIndicator: true, // 是否显示当前时间轴
allDaySlot: false, // 是否显示全天
slotEventOverlap: true, // 事件是否可重叠
editable: false, // 能否编辑事件。如果需要拖拽事件,必须开启它
droppable: true, // 是否把其它日历上的事件拖拽到这个日历上
selectOverlap: false, // 用户选择时能否重叠到事件上, selectable必须为true才生效
unselectAuto: true, // 选中时,点击页面其它位置是否取消选中
selectable: true, // 允许用户点击或拖拽选中
dayHeaders: true, // 是否显示日期标题
dayMinWidth: 'auto', // 日最小宽度,如果日期单元格没办法满足,会出现水平滚动条
refetchResourcesOnNavigate: true, // 当用户切换不同视图时,是否重新加载数据
resourceOrder: 'index', // 资源按照index属性排序
locale: util.cookies.get('lang').indexOf('en') > -1 ? 'en' : 'zh-cn', // 中英文
initialView: "dayGridMonth", // 默认视图
schedulerLicenseKey: "", // key,需要花钱
height: bodyHeight - 68, // 日历整体高度
eventSources: [], // 事件列表
resources: [], // 资源列表
plugins: [ // 用到的插件
momentPlugin,
dayGridPlugin,
timeGridPlugin,
resourceTimelinePlugin,
interactionPlugin,
resourceTimeGridPlugin,
scrollgridPlugin
],
headerToolbar: { // 标题显示的按钮和文本。
left: 'prev,title,mothTitle,next,today',
center: '',
right: 'timeGridDay,timeGridWeek,dayGridMonth,timeline'
},
buttonText: { // 按钮的文本设置
today: '今日',
dayGridMonth: '月',
week: '周',
day: '日'
},
customButtons: {
// 自定义button,如果想显示页面上,把timeline放到headerToolbar对象里。
timeline: {
text: '自定义',
click: this.timelineEvent
}
},
slotLabelFormat: 'HH:mm', // 资源视图的事件格式
eventTimeFormat: 'HH:mm', // 事件事件格式
dayMaxEvents: true, // 在dayGrid视图中如果每个单元格事件超出单元格会出现'+more'
resourceAreaWidth: '280px', // 横轴资源视图的左侧列表宽度
// 每个视图不同显示的日期格式
views: {
timeGridDay: {
titleFormat: { year: 'numeric', month: 'short', day: 'numeric'},
},
timeGridWeek: {
titleFormat: { year: 'numeric', month: 'short' },
},
dayGridMonth: {
titleFormat: { year: 'numeric', month: 'short' },
displayEventTime: true
},
timeline: {
titleFormat: { year: 'numeric', month: 'short', day: 'numeric'},
},
resourceTimeGrid: {
titleFormat: { year: 'numeric', month: 'short', day: 'numeric'},
duration: { days: 1 }
}
},
eventShortHeight: 15, // 具有最小事件的样式
slotDuration: "00:15", // 事件轴以15分钟为一刻度
eventMinHeight: "15", // 事件最小高度
// 出现+more会调用该回调。返回值为:文字或者DOM
moreLinkContent: (info) => this.$t('schedule.more') + info.num + this.$t('schedule.item'),
// 点击+more触发该回调
moreLinkClick: this.eventLimitClickFun,
// title标题文本回调。返回值为:文本和DOM
dayHeaderContent: this.columnHeaderHtmlFun,
// 取消选择回调
unselect: this.unselectCallback,
// 日期切换回调。注意:切换视图也会调用该回调。
datesSet: this.handleDatesRender,
// 点击事件
eventClick: this.handleEventClick,
// 切换视图
viewDidMount: this.handleViewSkeletonRender,
// 月视图每个单元格回调。返回值:文字或DOM
dayCellContent: (info) => {
return {html: `<a class="fc-daygrid-day-number">${info.dayNumberText.replace('日','')}</a>`}
},
// 现在指示器(nowIndicator)回调
nowIndicatorDidMount: this.nowIndicatorDidMount,
// 到当前时间指示器时间显示。如果有返回值(文本或DOM):则显示返回值
nowIndicatorContent: this.setNowIndicatorTime,
// 日历尺寸发生改变
windowResize: (arg) => {
this.fullcalendarResize(arg.view.type)
}
},
5. 结束
目前我使用FullCalendar5遇到的这些问题,如果有遇到新的问题,会实时更新到这里。
如果你使用FullCalendar5遇到过其它问题也可以在评论区告诉我。