接上文:微信小程序開發04-打造本身的UI庫css
github地址:https://github.com/yexiaochai/wxdemohtml
咱們這裏繼續實現咱們的日曆組件,這個日曆組件稍微有點特殊,算是相對複雜的組件了,而後通常的日曆組件又會有不少的變化,因此咱們這裏實現最基本的標籤便可:git
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>
這個是很是簡陋的日曆雛形,在代碼過程當中有如下幾點比較痛苦:github
① WXML與js間應該只有數據傳遞,根本不能傳遞方法,應該是兩個webview的通訊,而日曆組件這裏在WXML層由不得不寫一點邏輯web
② 原本在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 }
至此,咱們組件相關課題基本結束,接下來,咱們開始咱們的業務代碼