网站代码优化总结
图片上传
最近做项目涉及到用户拍照上传图片的,移动端的情况下,现在手机拍出来的照片随随便便就是好几兆,无论3/4G还WIFI要上传都很吃力,而且实际上手机上并用不到那么大。在网上发现了上传图片的时候可以通过js对图片进行压缩后,再处理或上传服务器。基本原理是通过canvas渲染图片,再通过 toDataURL 方法压缩保存为base64字符串(能够编译为jpg格式的图片)。
github:https://github.com/think2011/localResizeIMG
demo:http://think2011.net/localResizeIMG/test/
网页动画
要理解网页性能为什么不好,就要了解网页是怎么生成的。
网页的生成过程,大致可以分成五步。
- HTML代码转化成DOM
- CSS代码转化成CSSOM(CSS Object Model)
- 结合DOM和CSSOM,生成一棵渲染树(包含每个节点的视觉信息)
- 生成布局(layout),即将所有渲染树的所有节点进行平面合成
- 将布局绘制(paint)在屏幕上
这五步里面,第一步到第三步都非常快,耗时的是第四步和第五步。
"生成布局"(flow)和"绘制"(paint)这两步,合称为"渲染"(render)。
1.为了减少重排和重绘的次数,尽量把读和写操作分开
// bad div.style.left = div.offsetLeft + 10 + "px"; div.style.top = div.offsetTop + 10 + "px"; // good var left = div.offsetLeft; var top = div.offsetTop; div.style.left = left + 10 + "px"; div.style.top = top + 10 + "px";
2.虚拟DOM,visibility : hidden,position属性为absolute
或fixed
的元素。这些重绘代价较小,可以先把网页元素转化成这样,然后再进行操作。
参考:阮一峰 网页性能管理详解,http://www.ruanyifeng.com/blog/2015/09/web-page-performance-in-depth.html
html
1: 标签嵌套层级不要太深,标签尽量简洁化.如懒加载后将data
属性去除
2: DNS
预先处理 dns-prefetch
,如果一个页面有多个不同地址的引用,则DNS
预解析很有用。页面预先处理link
标签的prefetch
3: 大量图片的懒加载策略,以及一些元素利用ajax
在onload
后实行延迟加载
4: 对一些js
的异步加载
css
1: 嵌套层级不要太深,一般三层最多了。这个主要还是看团队项目结构,命名规范对这个有很大影响,互有取舍,是命名长一点不会有重复还是命名方便一点嵌套深一点
2: css
解析从右向左,所以最右边的应该是相对少一点的,比如.on.li_lick
就比.li_click.on
要好(如果.on
很多的话)
3: html
用了base64
的img
的话,并不会缓存起来,可以将这个base64
的图片放在css
文件里,css
会缓存,图片就缓存起来了
4: 尽量不用后代元素选择器,最右边的一层不要是标签,尤其是像div
这种非常常用的标签
5: 多使用css
的继承,而不是每一次都书写时都全部重写一遍。写多个css
属性时,能连在一起写的就连在一起写。如:background: #fff url() center center no-repeat
6:CSS背景图片可以通过坐标来实现对背景进行定位的,,那么我们可以将这些背景合并起来,这样即可减少http请求数
javascript
以一个for
循环来构建DOM
文档举例(使用jquery
)
// var lis = document.getElementsByTagName("li") var lis = [1, "2", "3", "4"]; var ulObj = $("ul"); var lisLength = lis.length; var html = ""; for (var i = 0; i < lisLength; i++) { if (lis[i] === 1) { html += '<li class="number">' + lis[i] + '</li>'; } else { html += '<li>' + lis[i] + '</li>'; } } ulObj.html(html);
01. 缓存变量。$("ul")
使用jquery
这种语句记得将其存在变量里,每一句$()
都是非常重的函数,能尽量少用就少用。
02. 使用诸如getElementsByTagName
这类LIVE
类型的collections
时,更要注意对其length
的缓存
03. var html = ""
。 赋值时,用字面量的方式
04. for
循环。实践证明,递减循环比递增循环要快那么一点点。
05. 对于大型的for
循环,可能导致执行时页面卡住,可以考虑使用数组分块技术将循环分割成多个循环一部分一部分的执行
06. for
循环里的条件判断lis.length
一定要缓存在变量里,不然每一次都要去查询一次长度。
07. 构建DOM
结构。一般有三种方式:
①: 使用节点关系createElement
,appendChild
这些去构建生成节点关系。
②:使用文档片段documentFragment
的方式。
③:直接用字符串拼接:这个又分为两种,直接+
号拼接和数组join
拼接。第三种速度效率最高。而第三种里面在移动端里使用+
号比数组快很多,在PC
端得看浏览器,不同浏览器不同版本对这两种方式的优化不同。
08. 插入到DOM
文档:使用innerHTML
的方式比appendChild
要效率高。综上,移动端还是使用+
号拼接字符串最后使用innerHTML
的方式
09. 插入到DOM
中时,一定要将插入结果放在变量里,在for
循环结束后插入,千万不能在for
循环中执行插入操作,会造成大量的重绘重排。尽量减少对DOM
的操作
10. 这个例子需要动态添加,动态删除,每个li
标签有click
事件。如果每次插入到DOM
后给li
添加click
事件,那么删除时就要清除注册在li
上的click
事件。非常麻烦。所以采用事件委托的机制,将事件绑定在ul
上,通过target
属来判断
11. 条件判断: ==
与 ===
,==
要进行类型转换比较,多了一个步骤,效率低
12. 使用直接函数,而不是与之等同的函数,比如$.ajax()
,其他$.get()
等最终都是调用$.ajax()
,多余的步骤多余的调用必然导致效率相对低
13. 选择器: 使用原生的选择器一定是最快的getElementById()
,getElementsByTagName()
这些,因为是用编译语言写好的方法。所以jquery
里$("li")
标签选取器的效率是很高的,所以$("li .my_li")
这样写比$(".my_li")
效率要高
14. 善用事件委托:如果有许多类似的结构要绑定事件,都利用事件冒泡的机制,在上层元素上绑定事件
15. 将一些多条件判断赋值语句用数组来做,比如:
switch(a) { case 0: result = "一"; break; case 1: result = "二"; break; }