封装组件库-日历

2023, Mar 13    

实现日历的封装

基于FullCalendar插件进行封装。

初始配置

  • 注册路由组件calendar,配置为Container组件的子路由组件
  • 采用路由懒加载,箭头函数异步引入组件。
  • 注册通用组件calendar,为路由组件的子组件,以便组件间通信。
  • 将通用组件calendar注册为全局组件

配置基础日历

  • 子组件props配置:
  let props = defineProps({
    //语言
    locale:{
      type: String,
      default: 'zh-cn'
    },
    //视图模式
    initialView:{
      type:String,
      default: 'dayGridMonth'
    },
    //按钮文字
    buttonText:{
      type: Object,
      default: ()=>{
        return {
          today: '今天',
          month: '月',
          week: '周',
          day: '日',
          prevYear: '上一年',
          nextYear: '下一年',
          prev: '上一月',
          next: '下一月'
        }
      }
    },
    //头部工具栏
    headerToolbar:{
      type: Object,
      default: ()=>{
        return {
          start: 'title',
          center: '',
          end: 'prev today next'
        }
      }
    },
    //底部工具栏
    footerToolbar:{
      type: Object,
      default: ()=>{}
    },
    //显示事件的结束时间
    displayEventEnd:{
      type: Boolean,
      default: false
    },
  })
  • 子组件渲染日历
  let renderCalendar = ()=>{
  let el = document.getElementById('calendar')
  if(el){
    calendar.value = new Calendar(el,{
      // 日历插件
      plugins:[daygrid,interaction],
      locale: props.locale,
      initialView: props.initialView,
      buttonText: props.buttonText, 
      headerToolbar: props.headerToolbar,
      footerToolbar: props.footerToolbar,
      displayEventEnd: props.displayEventEnd
  }

实现事件功能

  • 定义事件类型接口
  export interface EventItem {
    //事件标题
    title: string,
    //开始时间
    start: string,
    //结束时间
    end: string,
    //是否可拖拽
    editable?: boolean
  }
  • 子组件:props配置项添加。
  let props = defineProps({
    //事件源
    events:{
      type: Array as PropType<EventItem[]>,
      default:()=>[]
    }
   })
  • 在构造函数配置项添加事件源配置:判断events是否为空,callback进行渲染
  eventSources: [
    {
      //渲染日历事件
      events(e,callback){
        if(props.events.length) callback(props.events)
        else callback([])
      }
    }
  ],
  • 父组件传递events数据:通过添加editable实现可拖拽的功能。
  let events =  ref<EventItem[]>([
    {
      title: '购物',
      start: '2023-03-11 08:00',
      end: '2023-03-11 12:00',
      editable: true
    },
    {
      title: '敲代码',
      start: '2023-03-14 10:00',
      end: '2023-03-14 16:00' 
    }
  ])
  • 实现点击日期添加自定义事件:FullCalendar有dateClick、eventClick方法可通过点击具体实例获取日期和事件。通过分发事件发送给父组件,父组件向events里添加事件。
  • 子组件监听events的变化,调用渲染日历的方法重新渲染.
  dateClick(info: DateClickArg){
    emits('dateClick',info)
  },
  eventClick(info: EventClickArg){
    emits('eventClick',info)
  }
   <!-- 父组件向events里添加事件   -->
  let dataClick = (info: DateClickArg)=>{
    events.value.push({
      start: info.dateStr + ' 12:00',
      end: info.dateStr + ' 18:00',
      title: '学习'
    })
  }
  
  //监听父组件传递的事件源
  watch(()=>props.events,val=>{
    renderCalendar()
  },{deep:true})  

实现自定义事件渲染

  • 父组件传递方法eventContent(为FullCalendar配置项)
  • 创建el实例,timeText为事件的具体时间,拿到开始和结束时间,通过innerHTML定义样式,return 传入domNodes的数组实现自定义渲染。
  let eventContent = (arg: EventContentArg)=>{
    let el = document.createElement('div')
    let timeTextArr = arg.timeText.split('-')
    let start = timeTextArr[0].replace('上午','').replace('时',':00')
    let end = timeTextArr[1].replace('下午','').replace('时',':00')
    el.innerHTML = `
      <div>开始时间: ${start}</div>
      <div>结束时间: ${end}</div>
      <div>标题: ${arg.event._def.title}</div>
    `
    return {
      domNodes:[el]
    }
  }