zoukankan      html  css  js  c++  java
  • 微信小程序开发05-日历组件的实现

    接上文:微信小程序开发04-打造自己的UI库

    github地址:https://github.com/yexiaochai/wxdemo

    我们这里继续实现我们的日历组件,这个日历组件稍微有点特殊,算是相对复杂的组件了,然后一般的日历组件又会有很多的变化,所以我们这里实现最基本的标签即可:

     1 let View = require('behavior-view');
     2 const util = require('../utils/util.js');
     3 
     4 // const dateUtil = util.dateUtil;
     5 
     6 Component({
     7   behaviors: [
     8     View
     9   ],
    10   properties: {
    11     
    12   },
    13   data: {
    14     weekDayArr: ['日', '一', '二', '三', '四', '五', '六'],
    15     displayMonthNum: 1,
    16 
    17     //当前显示的时间
    18     displayTime: null,
    19     //可以选择的最早时间
    20     startTime: null,
    21     //最晚时间
    22     endTime: null,
    23 
    24     //当前时间,有时候是读取服务器端
    25     curTime: new Date()
    26     
    27   },
    28 
    29   attached: function () { 
    30     //console.log(this)
    31   },
    32   methods: {
    33    
    34   }
    35 })
     1 <wxs module="dateUtil">
     2   var isDate = function(date) {
     3     return date && date.getMonth;
     4   };
     5 
     6   var isLeapYear = function(year) {
     7     //传入为时间格式需要处理
     8     if (isDate(year)) year = year.getFullYear()
     9     if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) return true;
    10     return false;
    11   };
    12 
    13   var getDaysOfMonth = function(date) {
    14     var month = date.getMonth(); //注意此处月份要加1,所以我们要减一
    15     var year = date.getFullYear();
    16     return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
    17   }
    18 
    19   var getBeginDayOfMouth = function(date) {
    20     var month = date.getMonth();
    21     var year = date.getFullYear();
    22     var d = getDate(year, month, 1);
    23     return d.getDay();
    24   }
    25 
    26   var getDisplayInfo = function(date) {
    27     if (!isDate(date)) {
    28       date = getDate(date)
    29     }
    30     var year = date.getFullYear();
    31 
    32     var month = date.getMonth();
    33     var d = getDate(year, month);
    34 
    35     //这个月一共多少天
    36     var days = getDaysOfMonth(d);
    37 
    38     //这个月是星期几开始的
    39     var beginWeek = getBeginDayOfMouth(d);
    40 
    41     /*
    42         console.log('info',JSON.stringify( {
    43           year: year,
    44           month: month,
    45           days: days,
    46           beginWeek: beginWeek
    47         }));
    48     */
    49 
    50     return {
    51       year: year,
    52       month: month,
    53       days: days,
    54       beginWeek: beginWeek
    55     }
    56   }
    57 
    58   module.exports = {
    59     getDipalyInfo: getDisplayInfo
    60   }
    61 </wxs>
    62 
    63 
    64 <view class="cm-calendar">
    65   <view class="cm-calendar-hd ">
    66     <block wx:for="{{weekDayArr}}">
    67       <view class="item">{{item}}</view>
    68     </block>
    69   </view>
    70   <view class="cm-calendar-bd ">
    71     <view class="cm-month ">
    72     </view>
    73     <view class="cm-day-list">
    74 
    75       <block wx:for="{{dateUtil.getDipalyInfo(curTime).days + dateUtil.getDipalyInfo(curTime).beginWeek}}" wx:for-index="index">
    76 
    77         <view wx:if="{{index < dateUtil.getDipalyInfo(curTime).beginWeek }}" class="item active"></view>
    78         <view wx:else class="item">{{index + 1 - dateUtil.getDipalyInfo(curTime).beginWeek}}</view>
    79 
    80       </block>
    81 
    82       <view class=" active  cm-item--disabled " data-cndate="" data-date="">
    83 
    84       </view>
    85     </view>
    86   </view>
    87 </view>

    这个是非常简陋的日历雏形,在代码过程中有以下几点比较痛苦:

    ① WXML与js间应该只有数据传递,根本不能传递方法,应该是两个webview的通信,而日历组件这里在WXML层由不得不写一点逻辑

    ② 本来在WXML中写逻辑已经不太对了,而我们引入的WXS,使用与HTML中的js片段也有很大的不同

    这些问题,一度让代码变得复杂,而可以看到一个简单的组件,还没有复杂功能,涉及到的文件都太多了,这里是调用层:

    <ui-calendar  is-show="" ></ui-calendar>

    事实上,我们以上数据根本不应该写到data里面,应该属性传递,我们这里先为了简单实现功能,接下来我们继续完善这个组件,具体代码请看git:

    这个日历组件应该是在小程序中写的最复杂的组件了,尤其是很多逻辑判断的代码都放在了WXML里面,根据之前的了解,小程序渲染在一个webview中,js逻辑在一个webview中,他这样做的目的可能是想让性能更好,但是我这里代码写起来事实上是有点痛苦的,我们这里开始组装组件,将数据配置放到属性上,开始组装abstract-page,事实上我认为日历这种非全局组件本来不应该放到基类中:

    ① 因为Component提供的是一个标签,而且涉及的文件很多,加上继承关系很不好管理

    ② 因为日历组件事实上是一个标签,所以我们会有一个引入的基础WXML,一个使用的js,完全独立一个文件更加复杂

    ③ 本来小程序或者复杂的页面都应该组件化开发,所以我们简历一个页面级别的组件,分散到对应的页面中

    小程序像是给灵活的HTML&JS戴上了枷锁,只允许在其允许的范围灵活,我们这里尝试对页面进行再拆分:

    1 <import src="./mod.searchbox.wxml" />
    2 <view>
    3   <template is="searchbox" />
    4 </view>
    5 <include src="./mod/calendar.wxml"/>
    6 <include src="../../utils/abstract-page.wxml"/>
    <ui-calendar displayTime="{{CalendarDisplayTime}}"
    selectedDate="{{CalendarSelectedDate}}"
    displayMonthNum="{{CalendarDisplayMonthNum}}"
    is-show="{{isCalendarShow}}" ></ui-calendar>
     1 /*
     2 事实上一个mod就只是一个对象,只不过为了方便拆分,将对象分拆成一个个的mod
     3 一个mod对应一个wxml,但是共享外部的css,暂时如此设计
     4 所有日历模块的需求全部再此实现
     5 */
     6 module.exports = {
     7   q: 1,
     8   ddd: function(){},
     9 
    10   data: {
    11     isCalendarShow: '',
    12     CalendarDisplayMonthNum: 2,
    13     CalendarDisplayTime: new Date(),
    14     CalendarSelectedDate: null
    15   }
    16 }

    核心代码还是在abstract-page里面:

     1   //pageData为页面级别数据,mod为模块数据,要求一定不能重复
     2   initPage(pageData, mod) {
     3     //debugger;
     4     let _pageData = {};
     5     let key, value, k, v;
     6 
     7     //为页面动态添加操作组件的方法
     8     Object.assign(_pageData, this.getPageFuncs(), pageData);
     9 
    10     //生成真实的页面数据
    11     _pageData.data = {};
    12     Object.assign(_pageData.data, this.getPageData(), pageData.data || {});
    13 
    14     for( key in mod) {
    15       value = mod[key];
    16       for(k in value) {
    17         v = value[k];
    18         if(k === 'data') {
    19           Object.assign(_pageData.data, v);
    20         } else {
    21           _pageData[k] = v;
    22         }
    23       }
    24     }
    25 
    26     console.log(_pageData);
    27     return _pageData;
    28   }

    这里再改造一下,我们基本的日历组件便完成了80%了:

     1 /*
     2 事实上一个mod就只是一个对象,只不过为了方便拆分,将对象分拆成一个个的mod
     3 一个mod对应一个wxml,但是共享外部的css,暂时如此设计
     4 所有日历模块的需求全部再此实现
     5 */
     6 module.exports = {
     7   q: 1,
     8   ddd: function(){},
     9   onCalendarDayTap: function (e) {
    10     let data = e.detail;
    11     var date = new Date(data.year, data.month, data.day);
    12     console.log(date)
    13     this.setData({
    14       calendarSelectedDate: date
    15     });
    16   },
    17   data: {
    18     isCalendarShow: '',
    19     calendarDisplayMonthNum: 2,
    20     calendarDisplayTime: new Date(),
    21     calendarSelectedDate: null
    22   }
    23 }

    至此,我们组件相关课题基本结束,接下来,我们开始我们的业务代码

  • 相关阅读:
    20145127 《Java程序设计》第一周学习总结
    Java 问卷调查
    一个没有成就而即将退赛的OIer的告别书
    【深度优先搜索】MZOJ_1344工作依赖
    【算法随笔】最小生成树
    【数据结构】二叉树 学习笔记1
    【深度优先搜索】NOIP2017_D2T1 洛谷3958奶酪
    【树形DP】MZOJ_1063_士兵守卫
    【算法随笔】写一个自己的名词空间
    【树形DP】洛谷1122_最大子树和
  • 原文地址:https://www.cnblogs.com/yexiaochai/p/9412951.html
Copyright © 2011-2022 走看看