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
- }
- }
至此, 我们组件相关课题基本结束, 接下来, 我们开始我们的业务代码
来源: https://www.cnblogs.com/yexiaochai/p/9412951.html