实现一个基于vue框架的简单日历组件
今天闲着无聊写了个关于日历的组件玩玩,在这里记录一下实现方式。做一个简单的日历组件,只需要一个Date对象就可以完成了。要做的功能很简单。
1、获取某个月有多少天。
2、将每个月的天数和星期对应上。
3、点击上一月和下一月要切换不同月份的数据。
因为这个只是自己写着玩的,所以对布局和样式并没有太多的美化。组件略显粗糙。
日历在获取某个月个月有多少天时,只需要获取到某个月的最后一天即可,Date对象有个getDate方法是返回当天是几号的。如果没给Date对象传参数,默认获取当天,但是为了这里的Date对象可以复用,参数是需要从外面传进来的。所以写了个getPickData的方法:
获取相应的日期数据在日历里面除了天数我还需要把年和月显示出来,而且还需要对数据进行一下切割,所以我把所有需要的数据放到了对象中一并返回。上面的代码中,具体要获取那个月的日期,需要外部传入年和月,只要拿到年和月就能得到那个月有多少天,于是通过new Date(year,month,0)就能得到那个月的最后一天是几号,而号数和天数是对应的,比如new Date(2019,6,0),第三个参数传入0,那这个Date对象返回的就是2019年6月份的最后一天的号数,返回的是30,也就是30号。那6月就有30天。得到总天数在根据总的天数来循环就能得到1-30号的所有数。
在得到所有的天数之后,就需要让具体的日期和星期对应上,比如1号如果是周六,那1号应该对应到周六。因此我要先得到当月的1号是周几,通过getDay方法就能到具体的星期,Date对象所返回的星期数,是0-6,一共七天,0是周日,1-6就是周一到周六,因此需要做一个判断,为0的时候手动赋值为7。得到1号是周几时,在根据返回的星期数来往calendarDay数组头部添加空元素,1号如果是周六,那就应该往数组头部添加五个空字符串来占位。这个方法最后返回了一个对象,对象里面包含了拼接好的年和月,日期数组,当月1号对应的星期和切割好的数据格式。
对象包含的数据dayArr这个数组里面放的数据,才是真正需要显示出来的数据。dayArr数组的数据是根据calendarDay这个数组切割出来的:
分割数组一个星期只有七天,所以把数据处理成了单独的数组,一个数组包含七条数据,因此最后的数据格式就成了这样:
处理后的数据dayArr成了一个二维数组,这里或许不需要这么做,但我认为这样做了方便vue的循环。
循环数据现在需要对上个月和下个月的数据切换实现一下。有了上面的getPickData函数,数据的切换也就没什么事了,仅仅只是需要在点击对应按钮时调用一下getPickData函数给全局的变量重新赋值,点击上个月时需要判断一下是否为1月,如果是1月那年份要对应的减少并且月份置为12,相反,点击下个月时需要判断月份是否为12月,如果是12月则需要把年份加上去并且月份要置为1。
上一月和下一月在刚进入页面时还需要默认获取本月的数据。于是在vue里面的生命周期mounted中调用一次getPickData函数。
把第一次传入的年和月设置为全局变量是为了点击上个月和下个月切换数据时方便使用。
这个html的结构,周日是在最后面的,有很多日历周日是在最前面,如果要把周日放到最前面,那就需要修改几个地方。
两个th标签先调换一下位置。
上面我用的是空格在数组中占位,但很多组件,比如iview,elementui提供的日历组件,都是用上个月和下个月的数据来填充的,那我这里除了调换下周日的位置,也顺便用真实数据来填充。所以我需要对getPickData这个方法里面的代码修改一下,只需要把获取切割后数据的那句代码注释掉就好了。因为我不需要在这里切割数组,而是在后面切割。
注释获取切割数据然后我需要得到上个月的数据,比如这个月是8月,那我就需要得到7月的数据来填充到当前月的数据中。同时也需要得到下个月的数据来填充,但我没有获取下个月的数据,而是直接根据二维数组最后一条数据来手动填充,因为下个月的数据肯定是从1号开始的,所以不需要去刻意的获取。所以增加几个方法:
获取上个月的数据,实际上还是复用的getPickData,但传进去的参数是上个月月份。然后通过判断来截取上个月的数据,这里截取多少个是根据当前月的周几来计算的,比如说这个月的1号是周三,那周二就是上个月的最后一天,周一就是上个月的倒数第二天,周日就是倒数第三天。。。以此类推,如果本月1号是周三的情况下,我只需要填充周日周一周二就行了,所以要截取上个月数据的最后三天。在fillDate方法中第二个参数传进来的参数就是我之前得到的对象,对象下面有week属性,所以根据本月的周几来计算具体截取几条上月号数。然后把截取到的上个月最后几天号数替换掉之前的空格,重新返回回去。获取到了上个月的数据,现在要填充下个月的数据:
最后在填充下个月数据的时候就很粗暴了。直接循环判断二维数组中最后一个数组的数据item,将空字符串替换为12345....,所以最后得到的二维数组已经不是用空字符串占位了。
填充后的数据最后的日历就变成了这样,但其他的东西 比如上一个月 下一月的按钮也有一点小变动,之前是通过getPickData这个方法来得到最终数据,但我对那个逻辑进行了修改,那个方法返回的不在最终要显示的数据了,因此现在获取最终显示出来数据的方法成了fillNextData,所以上一月和下一月的方法也要相应的修改一下:
最后这个日历就变成了了真实数据填充的日历:
这个日历比较简单粗暴,但可以进行很多扩展,修改样式之后可以变得很好看,由于我使用的是table布局,因此还可以在th中添加额外标签来扩展一些后台系统的功能。也可以做成类似于iview那种弹出的小日历的组件进行选择等。因为是自己写着玩的,就不往下写了。只是记录一下基本日历的实现方式。