FullCalendar日历组件集成实战(10)

背景

有一些应用系统或应用功能,如日程管理、任务管理需要使用到日历组件。虽然Element Plus也提供了日历组件,但功能比较简单,用来做数据展现勉强可用。但如果需要进行复杂的数据展示,以及互动操作如通过点击添加事件,则需要做大量的二次开发。
FullCalendar是一款备受欢迎的开源日历组件,以其强大的功能而著称。其基础功能不仅免费且开源,为开发者提供了极大的便利,仅有少量高级功能需要收费。然而,尽管该组件功能卓越,其文档却相对简洁,导致在集成过程中需要开发者自行摸索与探索,这无疑增加了不少学习和验证的时间成本。
为此,本专栏通过日程管理系统的真实案例,手把手带你了解该组件的属性和功能,通过需求导向的方式,详细阐述FullCalendar组件的集成思路和实用解决方案。
在介绍过程中,我们将重点关注集成要点和注意事项,力求帮助开发者在集成过程中少走弯路,提供有效的避坑指南,从而提升开发效率,更好地利用这款优秀的日历组件。

官网:https://fullcalendar.io/
image.png
环境Vue3+Element Plus+FullCalendar 6.1.11。

使用

按需加载事件数据(三)

新的问题

上面我们实现了按需加载,详细测试时发现,自己添加的自定义按钮,控制隐藏或显示已完成的任务,不再有效……经分析和推测,问题很可能出在回调方法中的第二个参数successCallback,虽然我们做了缓存,但是高度怀疑这个方法只能使用一次,在已有数据的情况下,调用第二次,存在内部逻辑处理……
针对推测做了一个验证,源码如下:

//代码段1:传入未完成的任务
const filtedData = this.eventData.filter((item) => {
  return (
    item.status === 'IN_PROGRESS' ||
    item.status === 'TO_DO' ||
    item.status === 'EXPIRED' ||
    item.status === 'PENDING' ||
    item.status === 'PAUSED'
  )
})
this.successCallback(filtedData)

//代码段2:传入所有任务    
this.successCallback(this.eventData)

以上两段代码,次序对调,都是仅最前面的生效,并不是数据合并,实锤了回调方法successCallback只生效一次的推测。

把successCallback控制台打印了下,如下:

ƒ (res2) {
    if (!isResolved) {
      isResolved = true;
      normalizedSuccessCallback(res2);
    }
  }

其实不是successCallback自身变了,而是内部处理逻辑,有个isResolved状态位,一旦调用过一次后,该状态位就变了,第二次执行时状态位判断失败直接跳过处理了。

这么个机制,即使把数据过滤功能挪到后端进行,也照样无法解决问题。

尝试方案

日历组件内部是个黑盒,根据当前的现象和推测,目前最好的方式,就是重新触发下回调。
验证过一下几种解决方式,最终都没走通。
方式1:通过调用api来切换视图,实测无效,events属性对应的回调方法不会触发。

// 变更显示范围
changeShowScope() {
  this.showAllFlag = !this.showAllFlag
  // 触发回调
  const fullCalendar = this.$refs.fullCalendar.calendar
  const view = fullCalendar.view
  fullCalendar.changeView(view.type)
}

方式2:查阅文档发现有个做数据转换的方法,添加eventDataTransform事件回调,测试发现只触发一次。
方式3:官方还有个viewDidMount 回调方法,看文档说明也是在dom元素加载后触发一次,数据变化不会再次触发,也没戏。

以上方式统统无效。

解决方案

对于该问题,官方组件内置或扩展不太给力。考虑到我们自己添加的显示全部与未完成的数据过滤功能,实际使用过程中不会频繁操作,因此在点击切换按钮时,通过刷新当前tab页来实现数据刷新功能。
思路简单,实现起来有比较多的细节需要考虑。
当前用户的两个选择项,是显示全部任务还是仅显示未完成任务,以及浏览的视图类型,需要通过查询参数来缓存。

在页面mounted的时候,执行初始化,从query参数中获取和赋值,并调用日历组件的api来切换视图。

 mounted() {
    this.init()
  },
  methods: {
    // 初始化
    init() {
      this.calendarApi = this.$refs.fullCalendar.getApi()
      // 处理是否显示全部
      if (this.$route.query.showAllFlag != undefined) {
        //此处注意,query参数是字符串类型,直接赋值给showAllFlag会令其类型变化,使用非运算符!会一直为true
        this.showAllFlag = this.$route.query.showAllFlag == 'true' ? true : false
      }
      // 默认设置为日视图
      let viewType = this.calendarOptions.initialView
      // query参数中取值
      if (this.$route.query.viewType) {
        viewType = this.$route.query.viewType
      }
      // 调用日历组件api实现视图切换
      const fullCalendar = this.$refs.fullCalendar.calendar
      fullCalendar.changeView(viewType)
    },

配合前面说过的,将日历组件的事件源设置为函数方法,在该方法中监听视图变化获取数据范围变化。

calendarOptions: 
    ……
   // 加载事件数据
  events: this.loadEvent
   ……
}

  // 加载事件数据
loadEvent(fetchInfo, successCallback, failureCallback) { 
  this.startTime = this.$dateFormatter.formatUTCTime(fetchInfo.start)
  this.endTime = this.$dateFormatter.formatUTCTime(fetchInfo.end)
  this.successCallback = successCallback
  this.loadData()
 }

变更显示范围时,调用刷新,这里的刷新是调用了前端框架的tab页刷新,传入了query参数

// 变更显示范围
changeShowScope() {
  this.showAllFlag = !this.showAllFlag
  this.refresh()
},
// 刷新
refresh() {
  const fullCalendar = this.$refs.fullCalendar.calendar
  let query = this.$route.query

  query = Object.assign(query, {
    viewType: fullCalendar.view.type,
    showAllFlag: this.showAllFlag
  })
  refreshSelectedTagWithQuery(query)
}

进行功能测试,切换视图和变更数据显示全部还是未完成,前端显示正常。

查看后端情况情况,发现还有个小瑕疵,就是页面加载的时候,实际会触发两次调用后端服务请求,推测一次是来源于组件自身初始化加载,另一次是我们手工调用的api方法来切换视图。只有在切换显示范围时才会触发,影响很小,先搁置下,看看后面是否有更好的优化方式。

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-12 17:00:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-12 17:00:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-06-12 17:00:02       82 阅读
  4. Python语言-面向对象

    2024-06-12 17:00:02       91 阅读

热门阅读

  1. 2024年,计算机相关专业还值得选择吗?

    2024-06-12 17:00:02       26 阅读
  2. 22.正则化

    2024-06-12 17:00:02       29 阅读
  3. 一些常用的git指令总结

    2024-06-12 17:00:02       28 阅读
  4. 设计模式-单例模式

    2024-06-12 17:00:02       28 阅读
  5. 时间复杂度、空间复杂度,这里一次讲清楚

    2024-06-12 17:00:02       29 阅读
  6. 数智化招采平台多层级多租户能力的价值

    2024-06-12 17:00:02       26 阅读
  7. node设置镜像源详细教程

    2024-06-12 17:00:02       25 阅读
  8. 【使用ObjectSizeCalculator计算对象内存大小】

    2024-06-12 17:00:02       27 阅读
  9. Android常见内存泄漏场景总结

    2024-06-12 17:00:02       30 阅读