码迷,mamicode.com
首页 > 编程语言 > 详细

javascript动手写日历组件(3)——内存和性能优化(by vczero)

时间:2014-08-11 02:40:51      阅读:288      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   java   使用   os   

一、列表

javascript动手写日历组件的文章列表,主要是通过原生的JavaScript写的一个简约的日历组件:

(1)javascript动手写日历组件(1)——构建日历逻辑:http://www.cnblogs.com/vczero/p/js_ui_1.html

(2)javascript动手写日历组件(2)——优化UI和添加交互:http://www.cnblogs.com/vczero/p/js_ui_2.html

(3)javascript动手写日历组件(2)——内存和性能优化:http://www.cnblogs.com/vczero/p/js_ui_3.html

(4)github:https://github.com/vczero/UI

日历虽然很简约,但是作为基本使用可以满足要求,UI也相对清爽。

二、内存和性能优化

(1)手动移除事件处理程序

以为在DOM重绘的过程中,避免事件处理程序驻留内存,因此,手动XXX.onclik = null;

            for(var e = 0; e < 35; e++){
                var node = document.getElementById(‘vczero_celldom_‘ + e);
                node.onclick = null; //移除事件处理程序
                this.div.removeChild(node);
            }
        if(!!exist){
            exist.onclick = null;
            this.div.removeChild(exist);
        }

(2)将绑定事件处理程序改成事件委托

对于事件处理程序过多的问题,使用委托是最好的方式。事件委托实际上是事件冒泡,可以在父节点添加事件处理程序,然后,根据需要的目标节点,执行代码。具体的代码改进如下,将for循环中的事件绑定改为在this.div(父元素)上的事件委托:

 1         for(var i = 0; i < 35; i++){
 2             var cellDOM = document.createElement(‘div‘);
 3             cellDOM.style.width = cell.width + ‘px‘;
 4             cellDOM.style.height = cell.height + ‘px‘;
 5             cellDOM.style.display = ‘inline-block‘;
 6             cellDOM.style.float = ‘left‘;
 7             cellDOM.style.cursor = ‘pointer‘;
 8             cellDOM.style.textAlign = ‘center‘;
 9             cellDOM.id = ‘vczero_celldom_‘ + i;
10             cellDOM.style.lineHeight = cell.height + ‘px‘;
11             cellDOM.setAttribute(‘date‘,monthArr.date[i]); //设置日期对象到DOM属性date上
12             cellDOM.innerHTML = monthArr.date[i].getDate();
13             //去掉最后一行横线
14             if(i < 28){
15                 cellDOM.style.borderBottom = ‘1px solid #C8CACC‘;
16             }
17 
18             if(i < monthArr.preLen || i >= monthArr.currentLen + monthArr.preLen){
19                 cellDOM.style.color = ‘#BFBFBF‘;
20             }
21             this.div.appendChild(cellDOM);
22         }
23 
24         var _that = this;26         //使用父元素事件委托
27         this.div.addEventListener(‘click‘,function(e){
28             var node = e.target;
29             if(node.id.indexOf(‘vczero_celldom_‘) > -1){
30                 var date = new Date(node.getAttribute(‘date‘)).toLocaleString();
31                 callback(date);
32             }
33         });
34             if(i < monthArr.preLen || i >= monthArr.currentLen + monthArr.preLen){
35                 cellDOM.style.color = ‘#BFBFBF‘;
36             }
37             this.div.appendChild(cellDOM);
38         }
39 
40         var _that = this;
41         this.div.addEventListener(‘click‘,function(e){
43             var node = e.target;
44             if(node.id.indexOf(‘vczero_celldom_‘) > -1){
45                 var date = new Date(node.getAttribute(‘date‘)).toLocaleString();
46                 callback(date);
47             }
48         });

(3)本次修改还包括:

==>前一个月和下一个的日期变灰,本月黑色。

==>将,showUI函数改为回调,可以在调用时更为方便。

 1 <!doctype html>
 2 <html>
 3     <head>
 4         <meta charset="utf-8" />
 5         <script type="text/javascript" src="calendar.js"></script>
 6         <script type="text/javascript">
 7             function showCalendar(){
 8                 var c = new Calendar(calendar,new Date());
 9                 c.showUI(function(date){
10                     console.log(date);
11                 });
12             }
13         </script>
14     </head>
15     <body onload="showCalendar()">
16         <div id="calendar" style="width:390px; height:270px;"></div>
17     </body>
18 </html>

(4)整个JS代码,折叠起来吧。

bubuko.com,布布扣
  1 /*
  2 +------------------------------
  3 @author:vczero
  4 @time:2014/8/10
  5 @desc:简易日历组件
  6 +------------------------------
  7 */
  8 var Calendar = (function(){
  9     var Calendar = function(div, date){
 10         this.div = document.getElementById(div);
 11         var w = this.div.style.width || 390;
 12         var h = this.div.style.height || (300 - 30);
 13         this.width = parseInt(w) >= 360 ? w : 360; 
 14         this.height = parseInt(h) >= 180 ? h : 180;
 15         this.date = date;
 16         this.div.style.width = this.width + ‘px‘; //按默认值设置回去
 17         this.div.style.height = this.height + ‘px‘;//按默认值设置回去
 18     };
 19 
 20     Calendar.week = [‘星期一‘, ‘星期二‘,‘星期三‘, ‘星期四‘,‘星期五‘, ‘星期六‘, ‘星期日‘];
 21 
 22     Calendar.prototype.showUI = function(callback){
 23         var exist = document.getElementById(‘vczero_celldom_0‘);
 24         //如果存在节点:移除
 25         if(!!exist){
 26             for(var e = 0; e < 35; e++){
 27                 var node = document.getElementById(‘vczero_celldom_‘ + e);
 28                 node.onclick = null; //移除事件处理程序
 29                 this.div.removeChild(node);
 30             }
 31         }
 32 
 33         var width = this.width,
 34             height = this.height,
 35             cell = {width: (parseInt(width) - 20)/7, height: (parseInt(height) -30 - 20)/5},
 36             monthArr = this._monthPanel(this.date);
 37         this.div.style.paddingLeft = ‘8px‘; 
 38         this.div.style.border = ‘2px solid #57ABFF‘;
 39         this.div.style.cursor = ‘default‘;
 40         this.div.style.fontFamily = ‘微软雅黑‘;
 41         this._addHeader();
 42         this._addWeekday();
 43 
 44         for(var i = 0; i < 35; i++){
 45             var cellDOM = document.createElement(‘div‘);
 46             cellDOM.style.width = cell.width + ‘px‘;
 47             cellDOM.style.height = cell.height + ‘px‘;
 48             cellDOM.style.display = ‘inline-block‘;
 49             cellDOM.style.float = ‘left‘;
 50             cellDOM.style.cursor = ‘pointer‘;
 51             cellDOM.style.textAlign = ‘center‘;
 52             cellDOM.id = ‘vczero_celldom_‘ + i;
 53             cellDOM.style.lineHeight = cell.height + ‘px‘;
 54             cellDOM.setAttribute(‘date‘,monthArr.date[i]); //设置日期对象到DOM属性date上
 55             cellDOM.innerHTML = monthArr.date[i].getDate();
 56             //去掉最后一行横线
 57             if(i < 28){
 58                 cellDOM.style.borderBottom = ‘1px solid #C8CACC‘;
 59             }
 60 
 61             if(i < monthArr.preLen || i >= monthArr.currentLen + monthArr.preLen){
 62                 cellDOM.style.color = ‘#BFBFBF‘;
 63             }
 64             this.div.appendChild(cellDOM);
 65         }
 66 
 67         var _that = this;
 68         //使用父元素事件委托
 69         this.div.addEventListener(‘click‘,function(e){
 70             var node = e.target;
 71             if(node.id.indexOf(‘vczero_celldom_‘) > -1){
 72                 var date = new Date(node.getAttribute(‘date‘)).toLocaleString();
 73                 callback(date);
 74             }
 75         });
 76     };
 77 
 78     Calendar.prototype._addHeader = function(){
 79         var exist = document.getElementById(‘vczero_datediv‘);
 80         if(!!exist){
 81             exist.onclick = null;
 82             this.div.removeChild(exist);
 83         }
 84 
 85         var header = document.createElement(‘div‘);
 86         header.style.height = ‘22px‘;
 87         header.style.width = this.div.style.width || ‘800px‘;
 88 
 89         //包含左 时间 右的大DIV
 90         var dateDiv = document.createElement(‘div‘);
 91         dateDiv.style.width = ‘200px‘;
 92         dateDiv.style.height = ‘22px‘;
 93         dateDiv.style.margin = ‘0 auto‘;
 94         dateDiv.style.textAlign = ‘center‘;
 95         dateDiv.style.fontWeight = ‘bold‘;
 96         dateDiv.id = ‘vczero_datediv‘
 97 
 98         //< DIV
 99         var leftDiv = document.createElement(‘div‘);
100         leftDiv.innerHTML = ‘<‘;
101         leftDiv.style.display = ‘inline-block‘;
102         leftDiv.style.float = ‘left‘;
103         leftDiv.style.width = ‘50px‘;
104         leftDiv.style.cursor = ‘pointer‘;
105         leftDiv.style.color = ‘#C5BFBF‘;
106         var _that = this; //获取到this对象
107         leftDiv.addEventListener(‘click‘, function(event){
108             var year = parseInt(_that.date.getFullYear()),
109                 month = parseInt(_that.date.getMonth());
110             if(month === 0){
111                 _that.date = new Date(year - 1, 11, 1);
112             }else{
113                 _that.date = new Date(year, month - 1, 1);
114             }
115             _that.showUI();
116             
117         });
118 
119         //> DIV
120         var rightDiv = document.createElement(‘div‘);
121         rightDiv.innerHTML = ‘>‘;
122         rightDiv.style.display = ‘inline-block‘;
123         rightDiv.style.float = ‘left‘;
124         rightDiv.style.width = ‘50px‘;
125         rightDiv.style.cursor = ‘pointer‘;
126         rightDiv.style.color = ‘#C5BFBF‘;
127         rightDiv.addEventListener(‘click‘, function(event){
128             var year = parseInt(_that.date.getFullYear()),
129                 month = parseInt(_that.date.getMonth());
130             if(month === 11){
131                 _that.date = new Date(year + 1, 0, 1);
132             }else{
133                 _that.date = new Date(year, month + 1, 1);
134             }
135             _that.showUI();
136         });
137 
138 
139         //显示月份的DIV
140         var timeDiv = document.createElement(‘div‘);
141         timeDiv.style.display = ‘inline-block‘;
142         timeDiv.style.float = ‘left‘;
143         timeDiv.style.width = ‘100px‘;
144         timeDiv.innerHTML = this.date.getFullYear() + ‘年‘ + (this.date.getMonth() + 1) + ‘月‘;
145 
146         dateDiv.appendChild(leftDiv);
147         dateDiv.appendChild(timeDiv);
148         dateDiv.appendChild(rightDiv);
149         this.div.appendChild(dateDiv);
150     }
151 
152     //增加星期
153     Calendar.prototype._addWeekday = function(){
154         var exist = document.getElementById(‘vczero_week_0‘);
155         if(!!exist){
156             for(var i = 0; i < 7; i++){
157                 var node = document.getElementById(‘vczero_week_‘ + i);
158                 node.onclick = null;
159                 this.div.removeChild(node);
160             }
161             
162         }
163 
164         for(var i = 0; i < 7; i++){
165             var weekday = document.createElement(‘div‘);
166             weekday.style.width = (parseInt(this.width) - 20)/7 + ‘px‘;
167             weekday.style.height = ‘20px‘;
168             weekday.style.display = ‘inline-block‘;
169             weekday.style.float = ‘left‘;
170             weekday.style.color = ‘#BFBFBF‘;
171             weekday.style.fontWeight = ‘bold‘;
172             weekday.style.textAlign = ‘center‘;
173             weekday.id = ‘vczero_week_‘ + i;
174             weekday.innerHTML = Calendar.week[i];
175             this.div.appendChild(weekday);
176         }
177     }
178 
179     Calendar.prototype._monthPanel = function(date){
180         //如果传递了Date对象,则按Date对象进行计算月份面板
181         //否则,按照当前月份计算面板
182         var date = date || new Date(),
183             year = date.getFullYear(),
184             month = date.getMonth(),
185             day = date.getDate(),
186             week = date.getDay(),
187             currentDays = new Date(year, month + 1, 0).getDate(),
188             preDays = new Date(year, month, 0).getDate(),
189             firstDay = new Date(year, month, 1),
190             firstCell = firstDay.getDay() === 0 ? 6 : firstDay.getDay() - 1,
191             bottomCell =  35 - currentDays - firstCell;
192         //前一个月该显示多少天
193         var preMonth = [];
194         for(var p = firstCell; p > 0; p--){
195             preMonth.push(new Date(year, month - 1, preDays - p + 1));
196         }
197         var len = preMonth.length;
198         //本月
199         var currentMonth = [];
200         for(var c = 0; c < currentDays; c++){
201             currentMonth.push(new Date(year, month, c + 1));
202         }
203         //下一个月
204         var nextMonth = [];
205         for(var n = 0; n < bottomCell; n++){
206             nextMonth.push(new Date(year, month + 1, n + 1));
207         }
208 
209         preMonth = preMonth.concat(currentMonth, nextMonth);
210         return {
211             date: preMonth,
212             preLen: len,
213             currentLen: currentMonth.length
214         };
215     };
216 
217     return Calendar;
218 
219 })();
View Code

 

javascript动手写日历组件(3)——内存和性能优化(by vczero),布布扣,bubuko.com

javascript动手写日历组件(3)——内存和性能优化(by vczero)

标签:des   style   blog   http   color   java   使用   os   

原文地址:http://www.cnblogs.com/vczero/p/js_ui_3.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!