微信小程序开发(5):日历组件的实现

作者:叶小钗 

http://www.cnblogs.com/yexiaochai/p/9412951.html


接上文:

微信小程序开发(4):打造自己的UI库


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


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



let View = require('behavior-view');

const util = require('../utils/util.js');


// const dateUtil = util.dateUtil;


Component({

  behaviors: [

    View

  ],

  properties: {


  },

  data: {

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

    displayMonthNum: 1,


    //当前显示的时间

    displayTime: null,

    //可以选择的最早时间

    startTime: null,

    //最晚时间

    endTime: null,


    //当前时间,有时候是读取服务器端

    curTime: new Date()


  },


  attached: function () {

    //console.log(this)

  },

  methods: {


  }

})


<wxs module="dateUtil">

  var isDate = function(date) {

    return date && date.getMonth;

  };


  var isLeapYear = function(year) {

    //传入为时间格式需要处理

    if (isDate(year)) year = year.getFullYear()

    if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) return true;

    return false;

  };


  var getDaysOfMonth = function(date) {

    var month = date.getMonth(); //注意此处月份要加1,所以我们要减一

    var year = date.getFullYear();

    return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];

  }


  var getBeginDayOfMouth = function(date) {

    var month = date.getMonth();

    var year = date.getFullYear();

    var d = getDate(year, month, 1);

    return d.getDay();

  }


  var getDisplayInfo = function(date) {

    if (!isDate(date)) {

      date = getDate(date)

    }

    var year = date.getFullYear();


    var month = date.getMonth();

    var d = getDate(year, month);


    //这个月一共多少天

    var days = getDaysOfMonth(d);


    //这个月是星期几开始的

    var beginWeek = getBeginDayOfMouth(d);


    /*

        console.log('info',JSON.stringify( {

          year: year,

          month: month,

          days: days,

          beginWeek: beginWeek

        }));

    */


    return {

      year: year,

      month: month,

      days: days,

      beginWeek: beginWeek

    }

  }


  module.exports = {

    getDipalyInfo: getDisplayInfo

  }

</wxs>



<view class="cm-calendar">

  <view class="cm-calendar-hd ">

    <block wx:for="{{weekDayArr}}">

      <view class="item">{{item}}</view>

    </block>

  </view>

  <view class="cm-calendar-bd ">

    <view class="cm-month ">

    </view>

    <view class="cm-day-list">


      <block wx:for="{{dateUtil.getDipalyInfo(curTime).days + dateUtil.getDipalyInfo(curTime).beginWeek}}" wx:for-index="index">


        <view wx:if="{{index < dateUtil.getDipalyInfo(curTime).beginWeek }}" class="item active"></view>

        <view wx:else class="item">{{index + 1 - dateUtil.getDipalyInfo(curTime).beginWeek}}</view>


      </block>


      <view class=" active  cm-item--disabled " data-cndate="" data-date="">


      </view>

    </view>

  </view>

</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戴上了枷锁,只允许在其允许的范围灵活,我们这里尝试对页面进行再拆分:



<import src="./mod.searchbox.wxml" />

<view>

  <template is="searchbox" />

</view>

<include src="./mod/calendar.wxml"/>

<include src="../../utils/abstract-page.wxml"/>


<ui-calendar displayTime="{{CalendarDisplayTime}}"

selectedDate="{{CalendarSelectedDate}}"

displayMonthNum="{{CalendarDisplayMonthNum}}"

is-show="{{isCalendarShow}}" ></ui-calendar>


/*

事实上一个mod就只是一个对象,只不过为了方便拆分,将对象分拆成一个个的mod

一个mod对应一个wxml,但是共享外部的css,暂时如此设计

所有日历模块的需求全部再此实现

*/

module.exports = {

  q: 1,

  ddd: function(){},


  data: {

    isCalendarShow: '',

    CalendarDisplayMonthNum: 2,

    CalendarDisplayTime: new Date(),

    CalendarSelectedDate: null

  }

}


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


//pageData为页面级别数据,mod为模块数据,要求一定不能重复

  initPage(pageData, mod) {

    //debugger;

    let _pageData = {};

    let key, value, k, v;


    //为页面动态添加操作组件的方法

    Object.assign(_pageData, this.getPageFuncs(), pageData);


    //生成真实的页面数据

    _pageData.data = {};

    Object.assign(_pageData.data, this.getPageData(), pageData.data || {});


    for( key in mod) {

      value = mod[key];

      for(k in value) {

        v = value[k];

        if(k === 'data') {

          Object.assign(_pageData.data, v);

        } else {

          _pageData[k] = v;

        }

      }

    }


    console.log(_pageData);

    return _pageData;

  }


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


/*

事实上一个mod就只是一个对象,只不过为了方便拆分,将对象分拆成一个个的mod

一个mod对应一个wxml,但是共享外部的css,暂时如此设计

所有日历模块的需求全部再此实现

*/

module.exports = {

  q: 1,

  ddd: function(){},

  onCalendarDayTap: function (e) {

    let data = e.detail;

    var date = new Date(data.year, data.month, data.day);

    console.log(date)

    this.setData({

      calendarSelectedDate: date

    });

  },

  data: {

    isCalendarShow: '',

    calendarDisplayMonthNum: 2,

    calendarDisplayTime: new Date(),

    calendarSelectedDate: null

  }

}



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

感兴趣的小伙伴,可以关注公众号【grain先森】,回复关键词 “小程序”,获取更多资料,更多关键词玩法期待你的探索~

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

推荐阅读更多精彩内容

  • 找到fullcalendar.js, 找到代码为 isRTL:false,这句话 输入以下几句 monthName...
    迷你小小白阅读 1,531评论 0 1
  • 作者:叶小钗http://www.cnblogs.com/yexiaochai/p/9393212.html 前言...
    grain先森阅读 977评论 0 3
  • 四点半 这里的夜 冷得像一把火 死火烧掉白天 击落飞翔的云朵 四点半 城市没有活过来 今天完了 明天未生 老鼠都不...
    文子微阅读 366评论 2 10
  • 盯住树梢,方觉云飘。 闭目树下,也知叶摇。 一阵风,有形变幻, 未近也须应对拆招。 半生路,无数场景, 已远且待雾...
    珠江潮平阅读 295评论 5 19
  • (2016年10月2日) 对布达拉畏仰而幻想远离家乡炯目阿里飘荡守冬的寒风大雪把归路遮藏揣怀回家的方向留有尘封冰川...
    老葫芦阅读 229评论 0 1