react学习札记(三)--自己的日历控件
2016-03-20 13:34
495 查看
最近项目因需要一个个性化的日历,用react写了一个日历控件,如图所示
Safari对于js Date函数有一个坑,就是必须用最标准的形式如Date(YYYY/MM/DD),进行初始化,
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;记住了这些,以后再对元素进行居中,居左,居右的时候就不用担心自己不会啦。
(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; else today = 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; else attr_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"; }else pDOM.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"; }else pDOM.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;记住了这些,以后再对元素进行居中,居左,居右的时候就不用担心自己不会啦。
相关文章推荐
- React Native iOS环境搭建
- H5、React Native、Native应用对比分析
- 探索react native首屏渲染最佳实践
- ReactiveCocoa学习总结
- [React Native 笔记]几个命令行工具作用备忘
- React Native 实践小结
- React-Native schema跳转
- ReactNative页面跳转Navigator
- IOS集成React Native实现动态加载更新
- React中state与props介绍与比较
- 初探React与D3的结合-或许是visualization的新突破?
- ReactiveCocoa之UI篇
- ReactJS学习笔记——npm、JSX、webpack
- 学习使用React一步步搭建普通博客应用
- React-Native Android 学习笔记——1,配置环境
- 52、微信-扫一扫CaptureActivity
- 51、微信-发送朋友圈ShareActivity
- webpack+react+jquery和jquery插件
- React入门教程(一)
- React服务器端渲染