Vue基于flex布局的日历组件

详情请看:http://111.231.145.124:8006/MyBlog/#/lawrence/blog/details/fa60b805d54d2866edcc81c8994e6fe8

闲来无事,自己封装了一个简单的日历组件,将源码中的Calendar组件复制到自己的项目下即可使用,使用方式参考,组件使用说明

接下来,简单说明实现思路:

(1)首先,先完成页面的基本布局:

  <div class="calendar">

    <div class="month">

      <div class="month_select_left" v-on:click='prevMonth'>

        <div class='left'>

      <div class="month_select">{{year}}年{{month}}月

      <div class="month_select_right" v-on:click='nextMonth'>

        <div class='right'>

    <div class="week">

      <div v-for="(item,index) inweekArr" :key="index" class='weekday'>{{item}}

    <div class="date">

      <div class="column" v-for="(item, index) incolumnArr" :key="index">

        <div class="day" v-for="(item2,index2) in item" :key="index2" v-on:click="day_click(item2)">

          <div :class="{day_text:true,day_select:value=== item2.value&&value!=='',day_disabled:!item2.canSelect}">{{item2.index}}

  </div>

</template>

从上到下依次为month/week/day 重点在日期,默认当前日期当前月份,在js中去获取当月日期list,并进行一定的重组,通过两层循环,第一层是遍历它是第几行,第二层遍历第几个,每一行flex是1,每天flex:1,平均分为七份。以下是css:

.calendar{

    display: flex;

    flex: 1;

    flex-direction: column;

  }

  .week{

    display: flex;

    flex: 1;

    justify-content: center;

    align-items: center;

    background:  #f2f2f2;

    font-size: 26px;

    padding: 20px;

  }

  .weekday{

    display: flex;

    flex: 1;

    justify-content: center;

  }

  .month{

    display: flex;

    flex: 1;

    justify-content: center;

    align-items: center;

    font-size: 28px;

    height: 60px;

  }

  .month_select{

    display: flex;

    flex: 1;

    justify-content: center;

    align-items: center;

    height: 100%;

  }

  .month_select_left{

    display: flex;

    flex: 1;

    justify-content: flex-start;

    align-items: center;

    height: 100%;

    padding-left:50px;

  }

  .month_select_left:active{

    background-color: #e6e6e6

  }

  .month_select_right:active{

    background-color: #e6e6e6

  }

  .month_select_right{

    display: flex;

    flex: 1;

    justify-content: flex-end;

    align-items: center;

    height: 100%;

    padding-right:50px;

  }

  .left {

    border: solid #00A6E4;

    border-width: 0 3px 3px 0;

    /* display: inline-block; */

    padding: 5px;

    transform: rotate(135deg);

    height: 3px;

    width: 3px;

  }

  .right {

    border: solid #00A6E4;

    border-width: 0 3px 3px 0;

    /* display: inline-block; */

    padding: 5px;

    transform: rotate(-45deg);

    height: 3px;

    width: 3px;

  }

  .date{

    padding:0px 20px;

    text-align: center;

    font-size: 20px;

    display: flex;

    flex: 1;

    flex-direction: column;

    justify-content: center;

    align-items: center;

  }

  .column{

    display: flex;

    flex: 1;

    width: 100%;

    justify-content: center;

    align-items: center;

  }

  .day{

    display: flex;

    flex: 1;

    justify-content: center;

    align-items: center;

    font-size: 24px;

  }

  .day_text{

    width: 70px;

    float: left;

    height: 70px;

    line-height: 70px;

    /*margin:20px;*/

    /* background: blue; */

    border-radius: 70px;

  }

  .day_disabled{

    color:  #d9d9d9

  }

  .day_select{

    background:#00A6E4;

    color:white;

  }

在点击时触发事件,改变选中元素,同时选中元素和非选中以及不可选元素具有不同样式,通过class区分,点击向右,获取下个月日期list,同时也构造数组展示,向左同理,以下是js:

<script>

export default {

  name: 'Calendar',

  data () {

    return {

      year: '',

      month: '',

      day: '',

      weekArr: ['日', '一', '二', '三', '四', '五', '六'],

      dateArr: [],

      firstDay: '',

      lastDay: '',

      columnArr: []

    }

  },

  props: {

    value: {

      type: String,

      default: ''

    },

    list: {

      type: Array,

      default: function () {

        return []

      }

    },

    defaultValue: {

      type: String,

      default: new Date()

    },

    isSelectDefault: {

      type: Boolean,

      default: false

    }

  },

  mounted () {

    let selectDay = this.value === '' ? this.defaultValue : this.value

    this.getDate(selectDay)

    this.setDate()

  },

  methods: {

    getDate: function (time) { // 获取当月日期

      let mydate = new Date(time)

      let year = mydate.getFullYear()

      let month = mydate.getMonth()

      let months = month + 1

      this.year = year

      this.month = months

      this.day = mydate.getDate()

      let fist = new Date(year, month, 1)

      this.firstDay = fist.getDay()

      let last = new Date(year, months, 0)

      this.lastDay = last.getDate()

      if (this.isSelectDefault) {

        this.value = this.formatTimeToDate(time)

      }

    },

    // 构建日历数组

    setDate () {

      let dateArr = []

      let json = {}

      for (let i = 0; i < this.firstDay; i++) {

        json = {}

        json['index'] = ''

        json['value'] = ''

        json['canSelect'] = false

        dateArr.push(json)

      }

      for (let i = 1; i < this.lastDay + 1; i++) {

        json = {}

        json['index'] = i

        let value = this.formatTimeToDate(this.year + '-' + this.month + '-' + i)

        json['value'] = value

        json['canSelect'] = this.check_select(value)

        dateArr.push(json)

      }

    let last =7 -this.lastDay %7

    for (let i =0; i < last; i++) {

      json = {}

      json['index'] =''

      json['value'] =''

     json['canSelect'] =false

     json['canSelectRange'] =false

     dateArr.push(json)

}

      this.dateArr = dateArr

      let columnArr = []

      let array = []

      for (let i = 0; i < dateArr.length; i++) {

        array.push(dateArr[i])

        if (i % 7 === 6) {

          columnArr.push(array)

          array = []

        }

      }

      this.columnArr = columnArr

      console.log(columnArr)

      console.log(dateArr)

    },

    // 判断某日期是不是在可选范围内

    check_select (date) {

      let canSelectList = this.list

      for (let i = 0; i < canSelectList.length; i++) {

        if (date === canSelectList[i]) {

          return true

        }

      }

      return false

    },

    prevMonth () { // 上一月

      let months = ''

      let years = ''

      if (this.month === 1) {

        years = this.year - 1

        this.month = 12

        months = this.month

      } else {

        years = this.year

        months = this.month - 1

      }

      let first = new Date(years, months - 1, 1)

      this.firstDay = first.getDay()

      let last = new Date(years, months, 0)

      this.lastDay = last.getDate()

      this.month = months

      this.year = years

      this.setDate()

    },

    nextMonth () { // 下一月

      let months = ''

      let years = ''

      if (this.month === 12) {

        this.month = 0

        months = this.month

        years = this.year + 1

      } else {

        months = this.month + 1

        years = this.year

      }

      months = this.month + 1

      let first = new Date(years, months - 1, 1)

      this.firstDay = first.getDay()

      let last = new Date(years, months, 0)

      this.lastDay = last.getDate()

      this.month = months

      this.year = years

      this.setDate()

    },

    day_click (e) {

      if (e.index !== '' && e.canSelect) {

        this.value = e.value

        this.$emit('daySelect', e)

      }

      // console.log(this.data.day_select)

    },

    formatTimeToDate (time) {

      let today = new Date(time)

      let year = today.getFullYear()

      let month = ('0' + (today.getMonth() + 1)).slice(-2).toString()

      let date = ('0' + today.getDate()).slice(-2).toString()

      let dateString = year + '-' + month + '-' + date

      return dateString

    }

  }

}

</script>

第一次写技术博客,写的不好请见谅。

详细请看:http://111.231.145.124:8006/MyBlog/#/lawrence/blog/details/fa60b805d54d2866edcc81c8994e6fe8

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,914评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,935评论 2 383
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,531评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,309评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,381评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,730评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,882评论 3 404
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,643评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,095评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,448评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,566评论 1 339
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,253评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,829评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,715评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,945评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,248评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,440评论 2 348

推荐阅读更多精彩内容