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

一、列表

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代码,折叠起来吧。

  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 })();

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

时间: 2024-12-27 15:35:17

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

javascript动手写日历组件(2)——优化UI和添加交互(by vczero)

一.优化UI 继上一篇,http://www.cnblogs.com/vczero/p/js_ui_1.html.开始优化UI,主要优化的部分有: (1)增加星期行.(2)字体设置.(3)日期垂直居中.(4)将单元格->底部线条.(5)修改文本的颜色对比.(6)将内部调用的函数加前缀_,如_addHeader()._addWeekday(). 修改的后基本效果如下图: 整个代码做了小修小改: 1 var Calendar = function(div){ 2 this.div = documen

javascript动手写日历组件(1)——构建日历逻辑 (by vczero)

一.分析日历的组成部分和交互要素 (1)组成部分:选择年月部分.星期显示.包含本月(或者有前月和下一个月部分日子) (2)根据选择的年和月份,动态绘制日历面板. (3)一个日历 7(天) * 5(周) = 35格表格. (4)一个月份是统一的一个面板:一个月的头一天一定在日历面板的第一行,根据该天的“星期几”确定位置. (5)第一格子是星期一,最后一个格子是星期日,为5周的日历面板. 二.确定逻辑设计 日历上面的日历,8月1号建军节为什么会出现在这一格?因为一个月的天数是小于5周(35天)的,因

vue之手把手教你写日历组件

---恢复内容开始--- 1.日历组件 1.分析功能:日历基本功能,点击事件改变日期,样式的改变 1.结构分析:html 1.分为上下两个部分 2.上面分为左按钮,中间内容展示,右按钮 下面分为周几展示和日期展示 3.基本结构页面html书写 <template>    <div class="calender2">        <div class="date-header">            <div class

android 内存和性能优化汇总

1.即时编译(Just-in-time Compilation,JIT),又称动态转译(Dynamic Translation),是一种通过在运行时将字节码翻译为机器码,从而改善字节码编译语言性能的技术.即时编译前期的两个运行时理论是字节码编译和动态编译.Android原来Dalvik虚拟机是作为一种解释器实现,新版(Android2.2+)将换成JIT编译器实现.性能测试显示,在多项测试中新版本比旧版本提升了大约6倍. 2. 就像世界上没有免费的午餐,世界上也没有免费的对象.虽然gc为每个线程

CocosCreator内存与性能优化

本文主要跟大家一起来探讨一下Cocos Creator小游戏开发过程中内存优化.性能优化和包体优化. 一.内存优化 因为 iOS小游戏和微信共用同一个进程,而微信在连续两次收到系统内存警告的时候会关闭小游戏并释放小游戏占用的内存.如果你的小游戏有外网用户反馈“闪退”,或者你自己测试的时候频繁出现“该小程序可能导致微信响应变慢被终止”等提示,那么就应该是时候优化你的小游戏内存了! 1.优化双份纹理(必做!) 在你的项目中添加如下代码,就可以减少大量内存: 这里面的原理是,当Creator使用DOM

201506150846_《JavaScript权威指南(第六版)——性能优化10条、小写转大写、过滤、函数》(P162-168)

一. 权威指南 1. 对于类数组对象,我们不能用数组方法,但是我们可以用 Function.call(); 例如: Array.prototype.slice.call(arr,...); Array.prototype.silice.call(arr,...); Array.prototype.map.call(arr,...); 二. 性能优化10条 1.  var someId = document.getElementById('#someElem');  改成:  var docu =

android内存与性能优化

http://www.cnblogs.com/zyw-205520/archive/2013/02/17/2914190.html http://www.2cto.com/kf/201405/303276.html

JS JavaScript中的文档碎片 DocumentFragement JS性能优化

文档碎片是什么: 如果我们要在一个ul中添加100个li,如果不使用文档碎片,那么我们就需要使用append经常100次的追加,这会导致浏览器一直不停的渲染,是非常消耗资源的.但是如果我们使用文档碎片了,我们可以先将100个li添加到文档碎片中,然后直接把这个文档碎片追加到ul中即可.所以文档碎片其实就是一个临时的仓库. 如下代码在document.body中添加5个span for(var i=0;i<5;i++) { var op = document.createElement("s

[转载]网站前端性能优化之javascript和css——网站性能优化

之前看过Yahoo团队写的一篇关于网站性能优化的文章,文章是2010年左右写的,虽然有点老,但是很多方面还是很有借鉴意义的.关于css的性能优化,他提到了如下几点: CSS性能优化 1.把样式表置于顶部 现把样式表放到文档的< head />内部似乎会加快页面的下载速度.这是因为把样式表放到< head />内会使页面有步骤的加载显示. 注重性能的前端服务器往往希望页面有秩序地加载.同时,我们也希望浏览器把已经接收到内容尽可能显示出来.这对于拥有较多内容的页面和网速较慢的用户来说特