日历-不同状态下展示不同背景

625 阅读4分钟

日历组件

日历组件需求

  • 在日历中,根据不同的值展现其不同的样式。如现有一个学习时长记录的小程序,在每一天结束的时候填写当天的学习时长'studyTime'。
        if( studyTime <= 4 ) {
            当前日展示红色
        }else {
            当前日展示绿色
        }
    

日历组件展现形式

日历组件思路

  • 组件分为二块实现,表头和表体

  • 表头实现思路

    • 考量点:可能周日为每周的第一天,或者周一为每周的第一天
    • 具体思路:参照表头数据结构,需要关注的是每个对象的key值,key值将会用来与new Date(year,month,1).getDay()进行比对,匹配的值就代表当前月的第一天对应于第几个表头。表头数据结构:
      [
        {
          key: '0',
          label: '日',
        }, {
          key: '1',
          label: '一',
        }, {
          key: '2',
          label: '二',
        }, {
          key: '3',
          label: '三',
        }, {
          key: '4',
          label: '四',
        }, {
          key: '5',
          label: '五',
        }, {
          key: '6',
          label: '六',
        }
      ]
      
    • 如果需要对表头顺序进行切换,只需移动对象之间的顺序即可。但需要保证key值的闭环为0-1-2-3-4-5-6-0。至于第一个key到底是什么并不重要。
  • 表体实现思路:

    • 考量点:

      1. 状态样式显示:根据样图可以分析出一下几种情况

        1)相邻的日期如果与本身不一致,则背景为一个圆。如7号

        2)相邻的日期如果状态一致,则是一整块的背景,且最左边与最右边需要展示为半圆的样式。如12~15号

      思考1:怎样实现相邻状态一致则是一整块背景,如果不一致,则会有一定的间隔?如7号与8号。 思考2:状态该如何获取?

    • 解决方案:

      1. 渲染日历的数组calendarList长度为7 * 6,极端情况会出现月份占了六行的高度,所以使用7 * 6填充数组。也避免日历组件高度不固定。而calendarList内将根据情况自行填充

      2. ‘思考1’,实现的解决思路是:在每一个日期右侧放置一个填充块。该填充块颜色如何展示将依据相邻间的状态决定。

      3. ‘思考2’,思路是通过预先定义一个规则dateStatusRule,规则如下:

      dateStatusRule: {
        key: 'time', //key值:从后端传回的数据对象中取出‘key’值应用在此规则上
        range: [     //对应的key值>=8,则标记状态VALID、<8则标记状态INVALID
          {
            sign: '>=',
            value: '8',
            status: 'VALID'
          },
          {
            sign: '<',
            value: '8',
            status: 'INVALID'
          }
        ]
      },
      

      假使模拟数据为:

         mockData =  [{
      	"personName": "张三",
      	"date": "2019-11-01",
      	"time": 0
          }, {
          	"personName": "张三",
          	"date": "2019-11-02",
          	"time": 8
          }, {
          	"personName": "张三",
          	"date": "2019-11-03",
          	"time": 8
          }, {
          	"personName": "张三",
          	"date": "2019-11-04",
          	"time": 8
          }, {
          	"personName": "张三",
          	"date": "2019-11-05",
          	"time": 8
          }, {
          	"personName": "张三",
          	"date": "2019-11-06",
          	"time": 4
          }]
      
      • 声明一个长度为42的dateStatus数组用来存放日期状态。 let dateStatus = new Array(42).fill(''); 对mockData进行遍历获取对应date的status,并将status存放至dateStatus对应的位置。

      • calc.axml中在对calendarList进行遍历渲染时,通过索引获取当前日期所对应的status。在对相邻间的status进行比较来确定展现的样式。

      实现代码如下

          <block a:for="{{calendarList}}" a:for-item="item" a:for-index="index" key="{{index}}">
              <view class="calendar-item 
                          {{dateStatus[index] == 'VALID' ? 'calendar-green': (dateStatus[index] == 'INVALID' ? 'calendar-red': '')}}
                          {{dateStatus[index] == dateStatus[index+1] ? 'left-half-radius': 'full-radius'}}
                          {{ index > 0 && dateStatus[index - 1] == dateStatus[index] && dateStatus[index] == dateStatus[index+1]  ? 'square': ''}}
                          {{ index > 0 && dateStatus[index - 1] == dateStatus[index] && dateStatus[index] !== dateStatus[index+1]? 'right-half-radius': ''}}
                          {{ index > 0 && dateStatus[index - 1] !== dateStatus[index] && dateStatus[index] !== dateStatus[index+1]  ? 'full-radius': ''}}"
                         >
                <text>{{item}}</text>
              </view>
              <view class="calendar-placeholder
                          {{dateStatus[index] == 'VALID' && dateStatus[index] == dateStatus[index+1] ? 'calendar-green': 
                            dateStatus[index] == 'INVALID' && dateStatus[index] == dateStatus[index+1] ? 'calendar-red': ''
                          }}
                          {{dateStatus[index] == 'VALID' && index > 0 && dateStatus[index - 1] == dateStatus[index] && dateStatus[index] == dateStatus[index+1]  ? 'calendar-green': 
                            dateStatus[index] == 'INVALID' && index > 0 && dateStatus[index - 1] == dateStatus[index] && dateStatus[index] == dateStatus[index+1]  ? 'calendar-red': ''
                          }}">
              </view>
            </block>
            
          class解释:
              'square'--方块--border-radius: 0;
              'left-half-radius'--左半圆--border-radius: 50% 0 0 50%;
              'right-half-radius'--右半圆--border-radius: 0 50% 50% 0;
              
              'calendar-green'--绿色背景
              'calendar-red'--红色背景