avalon实现日期联动
前言
上一篇我们说了下Avalon的一些概念,以及一些主要特性,至于Avalon的一些基础教程,正美老师已经做了非常全面的讲述,参见:http://www.cnblogs.com/rubylouvre/p/3962848.html
以后我们将使用Avalon做几个实际的小例子,也是我在工作中使用中的东西,avalon的文档特别全,但是生产中使用的例子却非常少,所以我会在博客中多写些我工作中使用的例子。
这次先是一个日期联动组件,效果和源码请参照:http://runjs.cn/detail/vsuij302
这个简单的小组件能实现:1.默认三个下拉框选中的是当前的年月日。2.可自定义初始显示几年的数据。3.选择年和月的时候,可以自动判断日有多少天。4.当选择到1月31日时,切换成2月,自己定位到2月的最后一天,不会出错。
首先我们来看HTML部分
<div ms-controller="dateCtrl"> <select ms-duplex="year"> <option ms-repeat="yearArr">{{el}}</option> </select> <select ms-duplex="month"> <option ms-repeat="monthArr">{{el}}</option> </select> <select ms-duplex="day"> <option ms-repeat="dayArr">{{el}}</option> </select> </div>
HTML部分,第一首先定义了一个controller,然后是三个select下拉框,用于显示年、月、日;ms-duplex用于和VM中M层进行双向绑定,ms-repeat用于循环展示哪些年、哪些月、哪些日。
Avalon部分:
定义VM
var dateVM = avalon.define({ $id : "dateCtrl",//- controller的id yearsAgo : 10,//- 展示多少年 yearArr : [],//- 年的数组 year : 1,//- 年,用于监听 monthArr : [],//- 月的数组 month : 1,//- 月,用于监听 dayArr : [],//- 日的数组 day : 1//- 日,用于监听 });
定义VM部分比较简单,有注释,且都是必填项。
初始化部分
avalon.ready(function(){ date.init(dateVM); });
实现逻辑部分
//- 日期联动效果使用说明 //- 使用时, 需要在VM中定义下面6个参数, 调用init方法, 把当前VM作为参数传进去就可以 //- 如果没有日的选项, day和dayArr可定义 //- 注意:使用时, 在View层的select必须使用ms-duplex进行双向绑定 //- year : 1, //- month : 1, //- day : 1,(可不定义) //- yearArr : [], //- monthArr : [], //- dayArr : [](可不定义) var date = { init : function(dateVM) { var _this = this; _this.initDate(dateVM); if(dateVM.day) { dateVM.$watch("year", function(){//- 监听年, 重新渲染日 _this.renderDay(dateVM); }); dateVM.$watch("month", function(){//- 监听月, 重新渲染日 _this.renderDay(dateVM); }); } }, initDate : function(dateVM) { var _this = this; var yearArr = []; var monthArr = []; var dayArr = []; var today = new Date(); var year = today.getFullYear(); //- 填充yearArr, 只取当前年的前三年 for(var i=year-dateVM.yearsAgo; i<=year; i++) { yearArr.push(i); } dateVM.year = year;//- 放到VM中 dateVM.yearArr = yearArr;//- 放到VM中 var month = today.getMonth()+1; //- 填充monthArr, 每年有十二个月 for(var i=1; i<=12; i++) { monthArr.push(i); } dateVM.month = month;//- 放到VM中 dateVM.monthArr = monthArr;//- 放到VM中 if(dateVM.day) {//- 可能只需要年和月, 不需要日 var day = today.getDate(); //- 填充dayArr, 根据年和月的不同, 天数也不同 var lastDay = _this.getLastDay(year, month); for(var i=1; i<=lastDay; i++) { dayArr.push(i); } dateVM.day = day; dateVM.dayArr = dayArr; } }, renderDay : function(dateVM) { var _this = this; var lastDay = _this.getLastDay(dateVM.year, dateVM.month); if(dateVM.day > lastDay) {//- 解决当从5月切成2月时, 下拉为空的问题, 现在是定位到最后一天 dateVM.day = lastDay; } var dayArr = []; for(var i=1; i<=lastDay; i++) { dayArr.push(i); } dateVM.dayArr = dayArr; }, getLastDay : function(year,month){//- 获得某月的最后一天 var new_year = year;//- 取当前的年份 var new_month = month++;//- 取下一个月的第一天,方便计算(最后一天不固定) if(month>12) { new_month -=12;//- 月份减 new_year++;//- 年份增 } var new_date = new Date(new_year,new_month,1);//- 取当年当月中的第一天 return (new Date(new_date.getTime()-1000*60*60*24)).getDate();//- 获取当月最后一天日期 } }
这里重点说下$watch部分,因为需要在切换年和月的时候要动态的计算这个月有多少天(就是二月),所以监控年和月,当他们改变的时候,会计算有多少天,并重新把dayArr里面的数据清空,重新填充,这样VM就会自动同步到V中,而不像jQuery一个,根据ID或者class,重新选择DOM,
拼HTML