react学习札记(三)--自己的日历控件

来源:互联网 发布:韩国女主播软件 编辑:程序博客网 时间:2024/06/05 01:18

最近项目因需要一个个性化的日历,用react写了一个日历控件,如图所示

(function(global){flag = 0;var choice;var Calendar = function(div, date, datemoney){this.div = document.getElementById(div);var w = document.documentElement.clientWidth;var h = document.documentElement.clientHeight;this.width = w; this.height = h*3/5;this.date = date;this.div.style.width = this.width + 'px'; //按默认值设置回去this.div.style.height = this.height + 'px';//按默认值设置回去this.datemoney = datemoney;document.getElementById('header_date').innerHTML = this.date.getFullYear() + '年' + (this.date.getMonth() + 1) + '月';};Calendar.prototype['showUI'] = function(){var exist = document.getElementById('day_table');for(var i = 0; i < 42; i++){       var aim = document.getElementById('day'+i);       if (aim!=null && 1 == aim.getAttribute('flag'))       choice = aim.getAttribute('date');  }  //alert(choice);if(!!exist){this.div.removeChild(exist);}var width = this.width,    height = this.height,    cell = {width: width/7, height: (height -30 - 20)/6},    monthArr = this._monthPanel(this.date);this.div.style.cursor = 'default';this.div.style.fontFamily = '微软雅黑';var CurDate = new Date();var month = CurDate.getMonth()+1;var day = CurDate.getDate();var today;if(month>=10 && day >=10)today = CurDate.getFullYear()+"/"+month+"/"+day;else if(month>=10 && day <10)    today = CurDate.getFullYear()+"/"+month+"/0"+day;else if(month<10 && day >= 10)today = CurDate.getFullYear()+"/0"+month+"/"+day;elsetoday = CurDate.getFullYear()+"/0"+month+"/0"+day;var tableDOM = document.createElement('table');tableDOM.id = "day_table";//生成日历表格框架,通过monthArr向其中复制for(var i=0;i<42;i++){var attr_date;var attr_month = monthArr.date[i].getMonth()+1;var attr_day = monthArr.date[i].getDate();if(attr_month>=10 && attr_day >=10)attr_date = monthArr.date[i].getFullYear()+"/"+attr_month+"/"+attr_day;else if(attr_month>=10 && attr_day <10)    attr_date = monthArr.date[i].getFullYear()+"/"+attr_month+"/0"+attr_day;else if(attr_month<10 && attr_day >= 10)attr_date = monthArr.date[i].getFullYear()+"/0"+attr_month+"/"+attr_day;elseattr_date = monthArr.date[i].getFullYear()+"/0"+attr_month+"/0"+attr_day;if (i%7 == 0){var trDOM = document.createElement('tr');trDOM.id = "week"+parseInt(i/7);var tdDOM = document.createElement('td');var cellDOM= document.createElement('div');cellDOM.style.width = cell.width + 'px';cellDOM.style.height = cell.height + 'px';cellDOM.setAttribute('flag',"0");cellDOM.setAttribute('date',attr_date); var pDOM = document.createElement('p');if(cellDOM.getAttribute('date') == today){pDOM.innerHTML = monthArr.date[i].getDate()+"今日";pDOM.id = "now";}elsepDOM.innerHTML = monthArr.date[i].getDate();pDOM.style.marginTop = parseInt(cell.width/7)+'px';//pDOM.style.marginBottom = '0';cellDOM.appendChild(pDOM);cellDOM.className = 'day';cellDOM.id = 'day' + i;tdDOM.appendChild(cellDOM);trDOM.appendChild(tdDOM);tableDOM.appendChild(trDOM);}else{var tdDOM = document.createElement('td');var cellDOM= document.createElement('div');cellDOM.style.width = cell.width + 'px';cellDOM.style.height = cell.height + 'px';cellDOM.setAttribute('flag',"0");cellDOM.setAttribute('date',attr_date); //cellDOM.setAttribute('disabled','disabled');var pDOM = document.createElement('p');if(cellDOM.getAttribute('date') == today){pDOM.innerHTML = monthArr.date[i].getDate()+"今日";pDOM.id = "now";}elsepDOM.innerHTML = monthArr.date[i].getDate();pDOM.style.marginTop = parseInt(cell.width/7)+'px';//pDOM.style.marginBottom = '0';cellDOM.appendChild(pDOM);cellDOM.className = 'day';cellDOM.id = 'day' + i;tdDOM.appendChild(cellDOM);trDOM.appendChild(tdDOM);}if(i < monthArr.preLen || i >= monthArr.currentLen + monthArr.preLen){cellDOM.style.color = '#BFBFBF';}}this.div.appendChild(tableDOM);var date;//判断从外部传入的数组,加入日期对应的钱数for(var i = 0; i < 42; i++){      var aim = document.getElementById('day'+i);      //alert(this.datemoney);      for(date in this.datemoney){      if(aim!=null&&aim.getAttribute("date")==date && date>=today)      {        //test.style.backgroundColor = "#fedd00";        aim.setAttribute("money",this.datemoney[date]);        aim.className = "day hasmoney";        var money = document.createElement('p');        money.className = "money";        money.innerHTML = "¥"+this.datemoney[date];        aim.appendChild(money);//choice.style.border = "2px solid #fedd00";if(choice==aim.getAttribute('date')){aim.style.border = "2px solid #fedd00";aim.setAttribute('flag','1');}      }  }    }    //点击日期生成票的张数和总钱数$(".hasmoney").on("click",function(e){var node = e.target;if(node.id.indexOf('day') > -1 && node.className.indexOf('hasmoney') > -1){//callback(node.getAttribute('date'));if(1==node.getAttribute("flag") && flag == 1){node.setAttribute('flag',"0");node.style.border = "1px solid #C8CACC";document.getElementById('number').innerHTML = 0;flag = 0;document.getElementById('total-money').innerHTML = 0; }else if(0==node.getAttribute("flag")&& flag == 0){node.setAttribute('flag',"1");flag = 1;node.style.border = "2px solid #fedd00";document.getElementById('number').innerHTML = 1;document.getElementById('total-money').innerHTML = node.getAttribute('money');}if(0 == flag){document.getElementById('number').innerHTML = 0;document.getElementById('total-money').innerHTML = 0; }}});$(".money").on("click",function(e){var node = e.target.parentNode;if(node.id.indexOf('day') > -1 && node.className.indexOf('hasmoney') > -1){//callback(node.getAttribute('date'));if(1==node.getAttribute("flag") && flag == 1){node.setAttribute('flag',"0");node.style.border = "1px solid #C8CACC";document.getElementById('number').innerHTML = 0;flag = 0;document.getElementById('total-money').innerHTML = 0; }else if(0==node.getAttribute("flag")&& flag == 0){node.setAttribute('flag',"1");flag = 1;node.style.border = "2px solid #fedd00";document.getElementById('number').innerHTML = 1;document.getElementById('total-money').innerHTML = node.getAttribute('money');}if(0 == flag){document.getElementById('number').innerHTML = 0;document.getElementById('total-money').innerHTML = 0; }}});};Calendar.prototype._monthPanel = function(date){//如果传递了Date对象,则按Date对象进行计算月份面板//否则,按照当前月份计算面板var myDate = date || new Date(),    year = myDate.getFullYear(),    month = myDate.getMonth(),    day = myDate.getDate(),    week = myDate.getDay(),    currentDays = new Date(year, month + 1, 0).getDate(),    preDays = new Date(year, month, 0).getDate(),    firstDay = new Date(year, month, 1),    firstCell = firstDay.getDay() === 0 ? 6 : firstDay.getDay() - 1,    bottomCell =  42 - currentDays - firstCell;//前一个月该显示多少天var preMonth = [];for(var p = firstCell; p > 0; p--){preMonth.push(new Date(year, month - 1, preDays - p + 1));}var len = preMonth.length;//本月var currentMonth = [];for(var c = 0; c < currentDays; c++){currentMonth.push(new Date(year, month, c + 1));}//下一个月    var nextMonth = [];    for(var n = 0; n < bottomCell; n++){    nextMonth.push(new Date(year, month + 1, n + 1));    }    preMonth = preMonth.concat(currentMonth, nextMonth);    return {    date: preMonth,    preLen: len,    currentLen: currentMonth.length    };};global.Calendar = Calendar;})(window);
这段js是生成日历主体内容结构的。
Calendar.prototype._monthPanel
这个方法可作为一个api来使用,直接生成当月的天数,以及对应的情况。
var Share = React.createClass({  componentDidMount: function() {    var datemoney = new Array();//需要从外部得到的日期价钱对应表    datemoney["2016/03/01"] = "500";    datemoney["2016/03/17"] = "1000";    datemoney["2016/03/25"] = "5400";    datemoney["2016/04/23"] = "4000";    datemoney["2016/04/02"] = "4300";    (function(global){      //var calendar_codeshow = document.getElementById('calendar_codeshow');      var CurDate = new Date();      var year = CurDate.getFullYear();      var month = CurDate.getMonth()+1;      var day = CurDate.getDate();      var arr_date;      var arr_date_2;      for(arr_date in datemoney){        arr_date_2 = arr_date;        break;      }      var date = new Date(arr_date_2);      //日历      var calendar = new Calendar('calendar',date,datemoney);//      calendar.showUI();       $("#pre").on('click',function(e){        var year = parseInt(date.getFullYear()),        month = parseInt(date.getMonth());        if(month == 0){          date = new Date(year - 1, 11, 1);        }else{          date = new Date(year, month - 1, 1);        }        calendar = new Calendar('calendar',date,datemoney);//        calendar.showUI();       });      $("#next").on('click',function(e){        var year = parseInt(date.getFullYear()),        month = parseInt(date.getMonth());        if(month === 11){          date = new Date(year + 1, 0, 1);        }else{          date = new Date(year, month + 1, 1);        }        calendar = new Calendar('calendar',date,datemoney);//        calendar.showUI();       });      $('#add').on("click",function(e){        for(var i=0;i<42;i++){          var aim = document.getElementById('day'+i);          if(aim!=null && aim.getAttribute("flag") == 1){            //alert("if"+1 == flag && 1==aim.getAttribute("flag"));            //alert("e"+document.getElementById('number').innerHTML);            var money = parseInt(aim.getAttribute('money'));            if(1 == flag && 1==aim.getAttribute("flag")){              document.getElementById('number').innerHTML++;              //alert(document.getElementById('number').innerHTML);              var number = parseInt(document.getElementById('number').innerHTML);              document.getElementById('total-money').innerHTML = money * number;              //callback(money*number,number);            }          }        }      });      $('#reduce').on("click",function(e){        if(parseInt(document.getElementById('number').innerHTML)>1){        for(var i=0;i<42;i++){          var aim = document.getElementById('day'+i);          if(aim!=null && aim.getAttribute("flag") == 1){            var money = parseInt(aim.getAttribute('money'));            document.getElementById('number').innerHTML--;            var number = parseInt(document.getElementById('number').innerHTML);            //alert(money);            document.getElementById('total-money').innerHTML = money * number;            //callback(money*number,number);          }        }}      });      $('.submit').on('click',function(e){        var total_money = document.getElementById('total-money').innerHTML;        var number = document.getElementById('number').innerHTML;        alert(total_money);        alert(number);      });    })(this);  },  render: function(){    return (        <div id="calendar-main">          <div id="header">            <p className = "head-content">选择活动出发日期<button><img className="close" src="http://download.duckr.cn/wechat/service/close_btn.png" /></button></p>          </div>          <div id="calendar">            <table id ="week_table">              <tr>                <td><div>一</div></td>                <td><div>二</div></td>                <td><div>三</div></td>                <td><div>四</div></td>                <td><div>五</div></td>                <td><div>六</div></td>                <td><div>日</div></td>              </tr>            </table>            <table id = "header_table">              <tr>                <td><div id = "pre"><<上月</div></td>                <td><div id = "header_date"></div></td>                <td><div id = "next">下月>></div></td>              </tr>            </table>          </div>          <div id="bottom">            <div id ="reduce-add">购买数量              <button className="reduce"><img id="reduce" src="http://download.duckr.cn/wechat/service/minus_ticket.png"/></button>              <span className="zhang">张</span><span id="number">0</span>              <button className="add"><img id ="add" src="http://download.duckr.cn/wechat/service/add_ticket.png"/></button>            </div>            <button className="submit">支付(¥<span id="total-money">0</span>)</button>          </div>        </div>    );  } });React.render(React.createElement(Share , null),     document.getElementById('content'));
这是外部框架的js,也就是在这个js中调用calendar的。

Safari对于js Date函数有一个坑,就是必须用最标准的形式如Date(YYYY/MM/DD),进行初始化,new Date('2011-04-12'.replace(/-/g, "/"))这样就可以。

其他浏览器可以用相对宽松的形式如Date("2012-3-5")这种的都可以解析,很关键!Safari还有很多坑,比如一个在以前提过的,h5media播放器无法自动播放的情况,必须有一个用户的动作才能触发播放。(在safri on ios里面明确指出等待用户的交互动作后才能播放media,也就是说如果你没有得到用户的action就播放的话就会被safri拦截)

Safari在点击事件(onclick)中还有一个坑,需要给你的dom写一个css样式 cursor:pointer,因为safari认为这才是一个可点击区域。但是好像使用jQuery on绑定的点击事件就没有问题。。


最后还有个布局上的收获,如果需要在底部加一个其他颜色的蒙版,像最上面那个灰黑色蒙版,这时候不能用background-color+opacity,因为这样会使它下面所有的子div都是变透明,而应该在外面大div中使用css3中给出的rgba(0,0,0,0.7),前面三个代表颜色,最后一个代表透明度,用这种方法就是只在父div中有透明度。nice!


关于布局中的居中问题,可以参考下面这段话:

让行内元素水平居中显示,我们需要为其父级元素设置text-align:center,一般这个属性是用于将文字水平居中的,我们的行内元素就相当于一行之内的文字了,所以可以使用这个方法。
让块级元素,水平居中的办法是为块元素本身添加margin:0 auto;这样块级元素的左右边距就是自动的,也就可以在是水平方向上居中了。
不管是inline-block还是block,我们需要理解其居中的原理,是inline-block,就对其父级元素添加text-align:center,是块级元素就对其本身添加margin:0 auto;记住了这些,以后再对元素进行居中,居左,居右的时候就不用担心自己不会啦。


0 0