手把手编写一个Vue日历表组件

项目须要,须要一个日历表组件,产物狗厌弃第三方供应的组件款式太丑,功用不全,带刀和产物理论怎样产物有枪。无法只能本身写一个,宣布完这条博客我就提去职,再也不和产物多BB。
Html=>
`<template>

<div class="calender">
  <div class="calender-title-wrapper">
    <div class="calender-title">
      <div class="calender-arrow-item left2" v-if="false"></div>
      <div class="calender-arrow-item left1" @click="month--"></div>
      <div class="calender-Date-text">{{year}}年{{month}}月</div>
      <div class="calender-arrow-item right1" @click="month++"></div>
      <div class="calender-arrow-item right2" v-if="false"></div>
    </div>
  </div>
  <div class="calender-content-wrapper">
    <div class="calender-days-wrapper">
      <div class="calender-days">日</div>
      <div class="calender-days">一</div>
      <div class="calender-days">二</div>
      <div class="calender-days">三</div>
      <div class="calender-days">四</div>
      <div class="calender-days">五</div>
      <div class="calender-days">六</div>
    </div>
    <div class="calender-content">
      <div class="calender-item-wrapper"
           v-for="item in daysArr"
           :class="{'no-current-day':item.month!=month,
                    active:item === clickItemObj,
                    currentDay:item.day===_CurrentDate.day&&
                               item.month===_CurrentDate.month&&
                               item.year===_CurrentDate.year}"
           @click="_clickDaysItem(item)"
      >
        <div class="calender-item">{{item.day}}</div>
        <div class="tem-wrapper">
          <span class="temp" v-for="d in markArr" :style="{background: d.color}" v-if="_visibleTemp(d,item)"></span>
        </div>
      </div>
    </div>
    <div class="calender-mask-wrapper">
      <div class="calender-mask-item" v-for="item in markArr">
        <span class="tem" :style="{background:item.color}"></span>
        <span class="text">{{item.name}}</span>
      </div>
    </div>
  </div>
</div>

</template>`
js=>

<script>
    export default {
        name: "calender",
        props:{
          markArr:{
            type:Array,
            default(){
              return []
            }
          }
        },
        data(){
          return {
            day:'',
            month:'',
            year:'',
            currentDays:'',
            daysArr:[],
            clickItemObj:{}
          }
        },
        mounted() {
          this._getCurrentDate()
        },
        methods:{
          //点击日期
          _clickDaysItem(item){
            //选中日期标记与消除标记
            if(this.clickItemObj === item){
              this.clickItemObj = {}
            }else {
              this.clickItemObj = item
            }
            //非当前月份跳转
            if(item.month!=this.month){
              this.month = item.month
            }
            //传入事宜挑选回返
            this._user_defined_events(item)
          },
          //mark衬着
          _user_defined_events(item){
            for(let i=0;i<this.markArr.length;i++){
              if(this.markArr[i].days.includes(`${item.year}-${item.month}-${item.day}`)){
                this.$emit(this.markArr[i].clickEvent,item)
              }
            }
          },
          //是不是显现mark
          _visibleTemp(d,item){
            let dateStr = `${item.year}-${item.month}-${item.day}`
            return d.days.includes(dateStr)
          },
          //猎取月份天数
          _getDaysForMonth(year,month,type){
            let temp=new Date(year,month,type);
            let day = new Date(temp.getTime() - 864e5).getDate();
            this.currentDays = day
            this._getFirstDaysForMonth(this.year,this.month)
          },
          //猎取当前日期
          _getCurrentDate(){
            let date = new Date()
            this.day = date.getDate()
            this.month = date.getMonth()+1
            this.year = date.getFullYear()
            this._getDaysForMonth(this.year,this.month,1)

          },
          //猎取切换页月份第一天是周几与末了一天并猎取月前与月后弥补数组
          _getFirstDaysForMonth(year,month){
            let weekdays = new Date(`${year}-${month}-01`).getDay()
            let beforeMonthDaysArr = []
            let currentMonthDaysArr = []
            let afterMonthDaysArr = []
            //猎取上一月总天数
            if(month){
              let temp=new Date(year,month-1,1);
              let day = new Date(temp.getTime() - 864e5).getDate();
              for(let i=0;i<day;i++){
                beforeMonthDaysArr.push({
                  year:year,
                  month:month-1,
                  day:i+1
                })
              }
              beforeMonthDaysArr.splice(0,beforeMonthDaysArr.length-weekdays)
            }else{
              //12月
            }
            //猎取当前月总天数
            let temp=new Date(year,month,1);
            let day = new Date(temp.getTime() - 864e5).getDate();
            let afterWeekdays = new Date(`${year}-${month}-${day}`).getDay()
            for(let i=0;i<day;i++){
              currentMonthDaysArr.push({
                year:year,
                month:month,
                day:i+1
              })
            }

            if(beforeMonthDaysArr.length+currentMonthDaysArr.length+6-afterWeekdays===35){
              for(let i=0;i<13-afterWeekdays;i++){
                afterMonthDaysArr.push({
                  year:year,
                  month:month+1,
                  day:i+1
                })
              }
            }else{
              for(let i=0;i<6-afterWeekdays;i++){
                afterMonthDaysArr.push({
                  year:year,
                  month:month+1,
                  day:i+1
                })
              }
            }
            this.daysArr = [...beforeMonthDaysArr,...currentMonthDaysArr,...afterMonthDaysArr]
            //猎取下一月总天数
          }
        },
        watch:{
          'month'(){

            if(this.month===0){
              this.month = 12
              this.year--
            }
            if(this.month===13){
              this.month = 1
              this.year++
            }
            this._getDaysForMonth(this.year,this.month,1)
          }
        },
        computed:{
          _CurrentDate(){
            let date = new Date()
            let {day,month ,year} = {
              day:date.getDate(),
              month:date.getMonth()+1,
              year:date.getFullYear()
            }
            return {day,month ,year}
          }
        }
    }
</script>

css=>
tips:我用的css解析器是stylus,用less和sass之类的大佬贫苦动动你们的小手加个花括号

<style scoped lang="stylus">
  .calender
    text-align center
    min-width 280px
    height 400px
    .calender-title-wrapper
      height 44px
      line-height 44px
      .calender-title
        display flex
        margin 0 auto
        width 280px
        .calender-arrow-item
          flex 0 0 40px
          cursor pointer
          &.left1
            background url("icon_left.svg") no-repeat center
          &.left2
            background url("icon_left2.svg") no-repeat center
          &.right1
            background url("icon_right.svg") no-repeat center
          &.right2
            background url("icon_right2.svg") no-repeat center
        .calender-Date-text
          flex 1
          color #424242
          font-size 16px
    .calender-content-wrapper
      .calender-days-wrapper
        display flex
        height 44px
        line-height 44px
        margin-bottom 11px
        .calender-days
          flex 1
          color #A7A7A7
          font-size 14px
      .calender-content
        .calender-item-wrapper
          position relative
          float left
          width 14.285%
          height 44px
          line-height 44px
          color #686868
          cursor pointer
          .tem-wrapper
            position absolute
            left 50%
            height 10px
            width 40px
            transform translate3d(-50%,35px,0)
            font-size 0
            .temp
              position relative
              display inline-block
              line-height 10px
              width 6px
              height 6px
              background #4fff41
              border-radius 3px
              top -16px
              margin 0 2px
          .calender-item
            position absolute
            left calc(50% - 20px)
            top calc(50% - 20px)
            height 40px
            width 40px
            border-radius 20px
            line-height 40px
            &:hover
              background #FFC912
          &.no-current-day
            color #DCDCDC
          &.currentDay
            color #ffffff
            .calender-item
              background #FFC912
          &.active
            color #ffffff
            .calender-item
              background #FFC912
      .calender-mask-wrapper
        height 37px
        .calender-mask-item
          height 37px
          line-height 37px
          width 25%
          float left
          .tem
            margin-right 3px
            display inline-block
            height 8px
            width 8px
            border-radius 4px
          .text
            font-size 12px
</style>

给列位大佬呈上APP.vue中的挪用,以及参数细致用法
App.vue中的@test1事宜是在在入参markArr中定义的,个中在markArr中color是标记日期的款式色彩,name是显现的款式称号,days是日期数组,clickEvent就是自定义事宜称号

<template>
  <div id="app">
    <calender
      @test1="test"
      :markArr="[
      {
        color:'#76ff19',
        name:'测试一',
        days:['2019-5-8','2019-5-11','2019-5-14','2019-5-22'],
        clickEvent:'test1'
      },
      {
        color:'#ff1323',
        name:'测试二',
        days:['2019-5-9','2019-5-11','2019-5-3','2019-5-1'],
        clickEvent:'test2'
      },
      {
        color:'#ffc518',
        name:'测试三',
        days:['2019-5-18','2019-5-11','2019-5-7','2019-5-4'],
        clickEvent:'test3'
      },
      {
        color:'#ff26fc',
        name:'测试四',
        days:['2019-5-28','2019-5-11','2019-5-30','2019-5-31'],
        clickEvent:'test4'
      }
      ]"

    ></calender>
    <!--<backwards></backwards>-->
  </div>
</template>

<script>
  import calender from './components/calender/calender'
  import backwards from './components/backwards/backwards'
export default {
  name: 'App',
  components:{
    calender,
    // backwards
  },
  methods:{
    test(item){
      console.log(item)
    }
  }
}
</script>

<style lang="stylus">
#app
  position absolute
  height 100%
  width 100%
</style>

丢个效果图
《手把手编写一个Vue日历表组件》

是不是是很丑?我有意的,想要悦目本身改去吧,大抵功用全都完成了

    原文作者:crow
    原文地址: https://segmentfault.com/a/1190000019106859
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞