zoukankan      html  css  js  c++  java
  • 小程序-从零实现日历查看器

    先看一下效果吧,毕竟不知道我写的标题表达得够不够明确。

    有没有被帅到?标题说的日历查看器就是这个,那么下面我们来聊聊究竟该怎么实现这个强大好看(有点自恋)的日历查看(选择器)吧。

    先具体说一下思路吧:

    这个日历查看器其实最大的难点是怎么把月份和周的数据给对应上,其实利用数组很好解决这个问题,我们可以将月份的数据存入到数组中,日历表渲染就把这个数组遍历一下就好了。但在存入的时候,做一下小小的判断去给里面加几个空字符。那这个空字符是干嘛的呢?看下面一张图:

    空字符对应的就是红色框框中的内容,图片日历表中的数组是这样子的:["","",1,2,3,......];一直到30号,30号后面就不必再加了。

    上面就是基本的一个思路,下面看看应该怎么去做吧!

     第一步,我们先创建一个静态的数据渲染先:

    我把这个日历选择器分为两个部分,一个部分是操作那个部分,也就是有前进后退按钮那一个版块,另一个部分就是日历表,显示数据的部分。

    先把第一部分实现,代码如下:

     <!--日历控制器start-->
        <view class="hours-calendar flex-content border-top p-18">
            <view class="flex-content remote-ctr">
                <image src="/images/agent/pre-icon.png" bindtap="preYearFn"></image>
                <view class="margin-42 color-gray">{{years}}</view>
                <image src="/images/agent/next-icon.png" bindtap="nextYearFn"></image>
            </view>
            <view class="flex-content remote-ctr ml-27">
                <image src="/images/agent/pre-icon.png" bindtap="preMonthFn"></image>
                <view class="margin-42 color-gray">{{months}}月</view>
                <image src="/images/agent/next-icon.png" bindtap="nextMonthFn"></image>
            </view>
            <view class="ml-auto back-btn" bindtap="backToFn">
                回到今天
            </view>
        </view>
        <!--日历控制器end-->

    上面是.wxml文件的部分,那些图片其实是左右箭头类的,最后会给大家贴一下,有需要的朋友可以自行下载喔!

    接下来看看样式代码:

    .hours-calendar{
        padding: 35rpx 48rpx;
        background-color: #ffffff;
    }
    .remote-ctr image{
        width: 19rpx;
        height: 35rpx;
    }
    .margin-42{
        margin: 0 42rpx;
    }
    .ml-27{
        margin-left: 27rpx;
    }
    .back-btn{
        color: #ec6941;
        border-radius: 10rpx;
        border: 2rpx solid #ec6941;
        padding: 6rpx 21rpx;
    }
    .calendar-content{
        padding-bottom: 30rpx;
        background-color: #ffffff;
    }

    全局中公用的样式:

    .flex-content{
      display: flex;
      align-items: center;
    }
    .border-top{
      border-top: 2rpx solid #e8e8e8;
    }
    .color-gray{
      color: #a0a0a0;
    }
    .ml-auto{
      margin-left: auto;
    }

    实现第二部分日历表,同样利用强大的flex布局,然后让它去自动换行就ok了

    <view class="calendar-content p-18 color-gray border-top">
            <view class="flex-content week">
                <view></view>
                <view></view>
                <view></view>
                <view></view>
                <view></view>
                <view></view>
                <view></view>
            </view>
            <view class="flex-wrap week">
                <view data-day="{{item}}" wx:for="{{30}}" wx:key="key">{{item}}</view>
            </view>
        </view>

    加上样式:

    .calendar-content{
        padding-bottom: 30rpx;
        background-color: #ffffff;
    }
    .week view{
        width: 64rpx;
        height: 64rpx;
        text-align: center;
        line-height: 64rpx;
        margin-left: 38rpx;
        margin-top: 10rpx;
    }
    .is-today{
        border-radius: 50%;
        background-color: #dfdfdf;
        position: relative;
    }
    .is-today::after{
        content: "今天";
        position: absolute;
        bottom: -20rpx;
        left: -3rpx;
        font-size: 12rpx;
        width: 70rpx;
    }
    .se-day{
        border-radius: 50%;
        background-color: #ec6941;
        color: #ffffff;
    }

    这样一个静态的日历表就出来了,效果如下:

    有个0?这是数组遍历的惯性,大家知道就好了。

    那么接下来就是我们的重点了,究竟怎么让周和月份对应上?

    先创建一个日历js方法文件,calendar.js

    然后贴出代码:

    /**
     * 返回月份数组
     * @param year
     * @param month
     * @returns {*[]}
     */
    const getMonthList = function (year, month) {
        let date = new Date();
        if(year){
            date.setFullYear(year);
            date.setMonth(month - 1);
            date.setDate(1);
            let weekIndex = (date.getDay() - 1) < 0 ? 6 : (date.getDay() - 1);
            //获取本月总天数方法---将当前月份加1,下移到下一个月
            console.log(month + ',设置的月份为:' + date.getMonth());
            console.log('设置的礼拜为:' + weekIndex);
            date.setMonth(date.getMonth() + 1);
            //将当前日期置为0
            date.setDate(0);
            console.log('获取的天数为:' + date.getDate());
            //再获取天数即取上一个月的最后天数
            let days = date.getDate();
            let monthList =[];
            //周几开始加上总天数,就是所生产数组的总个数
            for(let i = 0; i < (weekIndex + days); i++){
                if(weekIndex > i){
                    monthList.push('');
                }else if((i) < (days + weekIndex + 1)){
                    monthList.push((i + 1) - weekIndex);
                }else {
                    monthList.push('');
                }
            }
            return monthList;
        }
    }
    module.exports = {
        getMonthList: getMonthList,
    }

    上述的思路就跟开篇上将的是一样的,可以对照上面一起看。

    有了这个方法之后,它可以根据我们传递的年份和月份,把一个带有空字符处理好的数组返回给我们。

    然后我们稍稍修改一下原来那个遍历的wx:for那里的代码:

    <view class="{{item === isToday ? 'is-today' : ''}} {{item === selectDay ? 'se-day' : ''}}" data-day="{{item}}" wx:for="{{calendarList}}" wx:key="key" bindtap="selectDayFn">{{item}}</view>

    在生命周期函数加载的时候,自动获取本月的日历表:

    /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        this.setData({
          groupId: Number(options.groupId),
        });
        wx.setNavigationBarTitle({
          title: options.name + '-工时'
        });
        this.backToFn();
      },

    上面用到的backToFn其实就是一个回到今天的函数,不过是跟初始加载是一样的。

    /**
       * 初始化当天日期数据
       */
      backToFn(){
        let _date = new Date();
        this.resetDataFn( _date.getFullYear(),_date.getMonth() + 1,_date.getDate());
      },

    什么?又包含了一个函数?这个resetDataFn是重点,下面会有四个函数会公用到,编程思想嘛,当然是能拆分就尽量拆分。

    /**
       * 数据重置
       * @param years 年份
       * @param months 月份
       * @param days 天
       */
      resetDataFn(years, months, days = this.data.isToday){
        this.setData({
          years:  years,
          months: months,
          isToday: days,
          calendarList: calendar.getMonthList(years,months),
        })
      },

    数据忘记初始化了:

    下面我们在小程序页面js文件中声明的几个变量:

    data: {
        calendarList: [],
        years: 0,
        months: 0,
        isToday: 0,
        selectDay: 0,
      },

    calendarList是日历表数组,years是年份,months是月份,isToday是天数,selectDay是被点击的天数(后面会用到)。

    等等,似乎还忘记了什么东西?还没实现怎么选择呢?

    变量声明好了,再来什么几个函数:Pages({})下。

    /**
       * 上一年
       */
      preYearFn(){
        let _date = new Date();
        console.log(`${this.data.months},${_date.getMonth() + 1}`);
        let _days = this.data.years - 1 === _date.getFullYear() && (_date.getMonth() + 1) === this.data.months ? _date.getDate() : 0;
        this.resetDataFn(this.data.years - 1, this.data.months, _days);
      },
      /**
       * 下一年
       */
      nextYearFn(){
        let _date = new Date();
        let _days = this.data.years + 1 === _date.getFullYear() && (_date.getMonth() + 1) === this.data.months ? _date.getDate() : 0;
        this.resetDataFn(this.data.years + 1, this.data.months, _days);
      },
      /**
       * 上一月
       */
      preMonthFn(){
        let _date = new Date();
        let _months = this.data.months - 1 === 0 ? 12 : this.data.months - 1;
        let _years = this.data.months - 1 === 0 ? this.data.years - 1 : this.data.years;
        let _days = (_date.getMonth() + 1) === _months && this.data.years === _date.getFullYear() ? _date.getDate() : 0;
        this.resetDataFn(_years, _months, _days);
      },
      /**
       * 下一个月
       */
      nextMonthFn(){
        let _date = new Date();
        let _months = this.data.months + 1 === 13 ? 1 : this.data.months + 1;
        let _years = this.data.months + 1 === 13 ? this.data.years + 1 : this.data.years;
        let _days = (_date.getMonth() + 1) === _months && this.data.years === _date.getFullYear() ? _date.getDate() : 0;
        this.resetDataFn(_years, _months, _days);
      },

    上面就是对应了四个按钮:

    就这样,一个强大霸气的日历选择查看器就完成了。

  • 相关阅读:
    基于三角形问题通过边界值分析和等价类划分进行黑盒测试
    小程序学习记录【数组操作相关(持续更新)】(1)
    Android实现九宫拼图过程记录
    高维数据Lasso思路
    CannyLab/tsne-cuda with cuda-10.0
    xgboost 多gpu支持 编译
    GDAL2.2.4 C#中的编译及使用
    SqlServer性能优化,查看CPU、内存占用大的会话及SQL语句
    WinForm任务栏最小化
    datatable与实体类之间相互转化的几种方法
  • 原文地址:https://www.cnblogs.com/liao123/p/12810842.html
Copyright © 2011-2022 走看看