Vue.js(18)之 封装calendar组件

Posted houfee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue.js(18)之 封装calendar组件相关的知识,希望对你有一定的参考价值。

效果

技术图片

 

 

需求

1、实现一个日历组件,如图:

 技术图片

2、显示某天的事项:

技术图片

3、事项是模拟父组件请求接口返回的,数据格式如下:

[
        
          id: ‘232‘,
          date: ‘2019-06-01‘,
          info: ‘我要去吃大餐‘
        ,
        
          id: ‘292‘,
          date: ‘2019-06-06‘,
          info: ‘我要去吃大餐‘
        ,
        
          id: ‘292‘,
          date: ‘2019-06-07‘,
          info: ‘我要去吃大餐‘
        ,
        
          id: ‘369‘,
          date: ‘2019-06-30‘,
          info: ‘我要去吃大餐‘
        
      ]

4、把事项添加到日历组件中,数据格式如下:

技术图片

 

代码解析

父组件页面:

<template>
  <div class="test-container">
    <h1>Test页面,测试组件</h1>
    <!-- 日历 -->
    <calendar v-if="calendarVisible" @getDateInfo="getDateInfo" :propsInfoList="propsInfoList" :propsTime="propsTime"></calendar>
  </div>
</template>

<script>
import calendar from @/components/Calendar/Calendar.vue
export default 
  name: test,
  components: 
    "calendar": calendar
  ,
  data() 
    return 
      calendarVisible: true,
      propsTime: ‘‘,
      propsInfoList: ‘‘,
      middle: [
        
          id: 232,
          date: 2019-06-01,
          info: 我要去吃大餐
        ,
        
          id: 292,
          date: 2019-06-06,
          info: 我要去吃大餐
        ,
        
          id: 292,
          date: 2019-06-07,
          info: 我要去吃大餐
        ,
        
          id: 369,
          date: 2019-06-30,
          info: 我要去吃大餐
        
      ]
    
  ,
  created() 
    this.propsInfoList = JSON.stringify(this.middle)
    this.propsTime = this.getToday()
  ,
  mounted() 
    window.alert(测试时间为19年 5、6、7月,完成是在6月)
  ,
  methods: 
    // 格式化当前日期 YYYY-MM-DD
    getToday() 
      let nowDate = new Date()
      let yy = nowDate.getFullYear().toString()
      let mm = (nowDate.getMonth() + 1 + ‘‘).padStart(2,0)
      let dd = (nowDate.getDate() + ‘‘).padStart(2,0)
      // let hh = nowDate.getHours().toString().padStart(2,‘0‘)
      // let mt = (nowDate.getMinutes() + ‘‘).padStart(2,‘0‘)
      // let ss = (nowDate.getSeconds() + ‘‘).padStart(2,‘0‘)
      return `$yy-$mm-$dd` // -$hh-$mt-$ss
    ,
    // 组件传值
    getDateInfo(year, month) 
      let _this = this
      _this.propsTime = `$year-$month`
      _this.calendarVisible = false
      setTimeout(() => 
        _this.propsInfoList = []
        let middle
        if(month == 05) 
          middle  = [
            
              id: 232,
              date: 2019-05-10,
              info: 我要去吃小餐
            
          ]
         else if (month == 06) 
          middle = _this.middle
         else if (month == 07) 
          middle  = [
            
              id: 232,
              date: 2019-07-10,
              info: 我要去吃小餐
            
          ]
         else 
          middle = ‘‘
        
        _this.propsInfoList = JSON.stringify(middle)
        _this.calendarVisible = true
      , 100)
    
  

</script>

日历子组件:

<template>
  <div class="calendar-container">
    <h1>calendar</h1>
    <div class="show-date" @click="clickData">showDate</div>
    <div class="now-time">今日:exactTime</div>
    <div class="calendar">
      <ul class="calendar-header">
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
      </ul>
      <ul class="calendar-body">
        <li class="calendar-row" v-for="(item, index) in JSON.parse(calendarData)" :key="index">
          <span v-for="(subItem, subIndex) in item" :class="[subIndex == 0 || subIndex == 6? ‘weekend‘: ‘weekday‘, subItem.type == ‘1‘? ‘exact-time‘: ‘‘, subItem.type == ‘0‘? ‘already-time‘: ‘‘, subItem.type == ‘2‘? ‘soon-time‘: ‘‘]" @click="showInfo(subItem)" :key="subIndex">
            subItem.date
          </span>
        </li>
      </ul>
    </div>
    <mt-popup v-model="popupVisible" position="bottom">
      <mt-picker :slots="slots" :showToolbar="true" :visibleItemCount="5" :itemHeight="itemsHeight" ref="picker">
        <img src="@/assets/images/picker_cancel.png" class="picker_cancel" v-on:click="cancelFunc()">
        <img src ="@/assets/images/picker_sure.png" class="picker_sure" v-on:click="sureFunc()">
      </mt-picker>
    </mt-popup>
  </div>
</template>

日历子组件逻辑:

import  MessageBox  from ‘mint-ui‘
export default 
  name: "calendar",
  props: 
    propsTime: String,
    propsInfoList: String
  ,
  data() 
    return 
      time: ‘‘,
      infoList: ‘‘,
      calendarData: [],
      showDate: ‘‘,
      exactTime: ‘‘,
      itemsHeight: 95 * window.screen.height / 1334,
      popupVisible: false,
      slots: []
    
  ,
  created() 
    this.infoList = this.propsInfoList
    this.time = this.propsTime.split(‘-‘)
    const date = this.getToday()
    this.exactTime = date.slice(0,3).join(‘-‘)
    this.getCalendar(...(this.time))
    this.getSlotsArray(...(date.slice(0,2)))
  ,
  methods: 
    // 日历组件
    getCalendar(year, month) 
      let _this = this
      const rightNow = _this.exactTime
      _this.showDate = `$year-$month
      const firstDate = new Date(year, month - 1, 1)
      const firstDay = firstDate.getDay()
      const isLeapYear = year % 100 == 0? year % 400 == 0? 1: 0: year % 4 == 0 ? 1: 0
      const monthArray = [31, 28 + isLeapYear, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
      const weeekLines =Math.ceil((monthArray[month - 1] + firstDay)/7)
      let calendar = []
      for(let i = 0; i < weeekLines; i++) 
        let weeekLinesInfo = []
        for(let j = 0; j < 7; j++) 
          const cellNo = i * 7 + j
          const datePerLine = cellNo - firstDay + 1
          if(datePerLine <= 0 || datePerLine > monthArray[month - 1]) 
            let outOfMonth = 
              "type" : ‘null‘,
              "date" : ‘‘
            
            weeekLinesInfo[j] = outOfMonth
           else 
            let day = (datePerLine + ‘‘).padStart(2,‘0‘)
            let inOfMonth = 
              "type" : ‘‘,
              "date" : day,
              "isDone": ‘‘,
              "infor": ‘‘
            
            const propsDate = `$year-$month-$day`
            if(propsDate == rightNow)
              inOfMonth.type = "1"
            
            const reservations = JSON.parse(_this.infoList)
            for(let k = 0; k < reservations.length; k++) 
              if(propsDate == reservations[k].date)
                // inOfMonth.type = "1"
                inOfMonth.infor = reservations[k].info
                if(rightNow == reservations[k].date) 
                  inOfMonth.type = "1"
                  inOfMonth.isDone = "doing"
                 else if (rightNow > reservations[k].date) 
                  inOfMonth.type = "0"
                  inOfMonth.isDone = "pass"
                 else if (rightNow < reservations[k].date) 
                  inOfMonth.type = "2"
                  inOfMonth.isDone = "will"
                
              
            
            weeekLinesInfo[j] = inOfMonth
          
        
        calendar.push(weeekLinesInfo)
      
      window.console.log(calendar)
      _this.calendarData = JSON.stringify(calendar)
    ,
    // 格式化当前日期 YYYY-MM-DD
    getToday() 
      let nowDate = new Date()
      let yy = nowDate.getFullYear().toString()
      let mm = (nowDate.getMonth() + 1 + ‘‘).padStart(2,‘0‘)
      let dd = (nowDate.getDate() + ‘‘).padStart(2,‘0‘)
      let hh = nowDate.getHours().toString().padStart(2,‘0‘)
      let mt = (nowDate.getMinutes() + ‘‘).padStart(2,‘0‘)
      let ss = (nowDate.getSeconds() + ‘‘).padStart(2,‘0‘)
      return [yy, mm, dd, hh, mt, ss]
      // return `$yy-$mm-$dd-$hh-$mt-$ss`
    ,
    // 组装 picker 数组
    getSlotsArray(year, month)
      let _this = this
      let yearArray = []
      for(let i = -10 ; i <= 10 ; i ++)
        yearArray.push(year - 1 + i)
      
      let monthArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
      let slots = [
        
          values:yearArray,
          className:"slot1",
          defaultIndex: 11
        ,
        
          values:monthArray,
          className:"slot2",
          defaultIndex:month - 1
        
      ]
      _this.slots = slots
    ,
    // 显示日期弹窗
    clickData()
      this.popupVisible = true
    ,
    // 取消按钮
    cancelFunc()
      this.popupVisible = false;
    ,
    // 确认按钮
    sureFunc() 
      let _this = this
      _this.popupVisible = false
      const clickData = _this.$refs.picker.getValues()
      const year = clickData[0] + ‘‘
      const month = (clickData[1] + ‘‘).padStart(2,‘0‘)
      const day = _this.time[2]
      _this.getDateInfo(year, month)
      _this.getCalendar(year, month)
    ,
    // 调用父组件定义的方法
    getDateInfo(year, month) 
      this.$emit(‘getDateInfo‘, year, month)
    ,
    // 点击展示某天的事项信息
    showInfo(info) 
      let _this = this
      const infor = info
      if(infor.infor) 
        const [year, month] = _this.showDate.split(‘-‘)
        console.log(year, month, info)
        const titleDate = `$year-$month-$info.date`
        const preview = info.infor
        MessageBox(
          title: titleDate,
          message: preview,
          showCancelButton: false,
          closeOnClickModal: true
        )
      
    
  

 

其他:为了减少篇幅,省略样式

github地址

以上是关于Vue.js(18)之 封装calendar组件的主要内容,如果未能解决你的问题,请参考以下文章

vue03

vue之组件

vue基础(下篇)

Vue组件之全局组件与局部组件

Vue组件之全局组件与局部组件

Vue.js(20)之 封装字母表(是这个名字吗0.0)