微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

JavaScript优化以及前段开发小技巧

一、网络优化

YSlow有23条规则,中文可以参考这里。这几十条规则最主要是在做消除或减少不必要的网络延迟,将需要传输的数据压缩至最少。

1)合并压缩CSS、JavaScript、图片,静态资源CDN缓存

通过构建工具Gulp,可以在开发的时候就将合并压缩的事情一起做掉。

之所以要做合并压缩是因为:HTTP 1.x不允许一个连接上的多个响应数据交错到达(多路复用),因而一个响应必须完全返回后,下一个响应才会开始传输。

也就是说即使客户端同时发送了两个请求,而且CSS资源先准备就绪,服务器也会先发送HTML响应,然后再交付CSS。

使用CDN是为了让用户访问的时候能用最近的资源,减少来回传输时间。

HTTP2.0改进了HTTP1.x很多方面。

底部

CSS可以并行下载,而JavaScript加载之后会造成阻塞。

但凡事还是会有例外,如果把行内脚本放在样式表之后,会明显地延迟资源的下载(结果是样式表下载完成并且行内脚本执行完毕时,后续资源才能开始下载)。

这是因为行内脚本可能含有依赖于样式表中样式的代码,比如document.getElementsByClassName()。

rush:js;">

下面通过Chrome的工具查看下:

重定向

在做一个“女神评选活动”的时候,需要在微信中访问能够获取用户的openid,微信获取用户基本信息是需要经过几个步骤的:

获取code,再通过code获取openid,最后再跳转访问静态页面

由于公司将业务分成了多个小组,所以短短的三步其实需要三个小组配合,需要重定向多个域名。

下图是未优化前的瀑布图,但不是最坏情况,有时候访问到静态页面需要经过10多秒,完全不能接受,下图中会跳转4个域名:

后面不跳index那个域名,直接跳转到微信操作域名,减少一个域名的跳转,各小组代码再做优化,但效果还是不理想,仅仅快了几秒。

最后发现其实是在与微信的服务器做交互的时候,DNS解析花了太多时间!不得已,在服务器的host中添加一条记录,直接通过IP指向。

下图是最终优化结果,虽然达不到秒开,但至少可以接受了:

二、JavaScript优化

图片预加载

在做一个“秋名山活动”的时候,使用了图片预加载。这个活动中有120多张图片

流程很简单,就是答题,最后给评论结果,再分享出去。

如果一下子加载那么多图片,一定是愚蠢的想法,最后决定,在页面载入的时候先加载一些通用图片

在答题的时候当前页面,预先加载后面页面中的图片,防止访问页面的时候直接不展示图片图片也做了适当的合并。

网站地址放在gtmetrix.com测试,下面是最终的瀑布图,可以发现图片都在其他静态资源的后面,这样能尽早的展现页面用户

优化还远远没有结束,在Chrome中分别模拟了good 2G、good 3G以及4G后,有结果的情况并不理想。

good 2G:

  

good 3G:

  

4G:

  

还有很大的优化空间可以做,关于这个预加载的原理,可以参考《图片预加载与懒加载》

在写业务逻辑的时候,经常会用到if else,switch之类的逻辑判断,如果每次都做这么多判断,很容易影响性能

所以可以通过多种方式来避免过多的判断。

1. 惰性模式

这是在看《JavaScript设计模式》的时候看到的。

减少每次代码执行时的重复性分支判断,通过对对象重定义来屏蔽原对象中的分支判断。

惰性模式分为两种:第一种文件加载后立即执行对象方法来重定义,第二种是当第一次使用方法对象时来重定义。

公司有个页面要提供给第三方APP,但是最终发现第三方APP不能使用localStorage缓存,最终只得做兼容的方式。

但为了避免每次引用方法的时候都做判断,就使用加载后立即重定义:

rush:js;"> var getFn = function() { if (sore.enabled) return sore.get; return cookie.get; }(); var setFn = function() { if (sore.enabled) return sore.set; return cookie.set; }();

2. 建立映射关系

页面中经常需要弹出框提示,后面就自己做了一个,但弹出框会有很多款式。

如果用简单工厂模式创建的话,免不了switch分支判断,后面就直接用赋不同的key,还能缓存起来,只初始化一次。

rush:js;"> /** * 弹出框单例模式 */ var factories = {}; var DialogFactory = function(type,options) { if (factories[type]) return factories[type]; return factories[type] = new iDialog(options); }; /** * 提示框 */ var Alert = function(content,options) { var d = DialogFactory('alert',options); //其他逻辑省略 return d; }; /** * 确认框 */ var Confirm = function(content,options) { var d = DialogFactory('confirm',options); //其他逻辑省略 return d; };

代码异步加载

第三方代码,例如百度统计、微信SDK等,这些完全可以在将业务资源加载完后再添加

/**
 * 百度统计设置
 */
util.baidu = function(key) {
 global._hmt = global._hmt || [];
 (function() {
  var hm = document.createElement("script");
  hm.src = "//hm.baidu.com/hm.js?" + key;
  var s = document.getElementsByTagName("script")[0];
  s.parentNode.insertBefore(hm,s);
 })();
};

有了缓存后,就能减少与服务器的通信,在本地操作。

公司有个查违章的业务,在本地添加好车辆后,再次进入页面的时候就需要能直接选择事先添加好的车辆。

最理想的方式就是添加好后,就在本地缓存起来,下次进入直接调取缓存。

我会优先使用localStorage,下面的表格就是对比:

cookie

localStorage

数据生命周期

可设置失效时间除非被清除,否则永久保存

数据大

大约4KB 大约5M

与服务器通信

每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题 不参与和服务器的通信

本地存储,之前的历史大概如下图所示:

localStorage在浏览器兼容方面,IE8居然也支持了。

使用事件委托技术能让你避免对特定的每个节点添加事件监听器。

事件监听器是被添加到它们的父元素上,通过事件冒泡,触发执行。

在开发的时候,经常会出现动态添加元素的情况。

如果每次都重新绑定一次事件,那会有很多多余操作,而绑定在此元素的父级,就只需绑定一次即可。

rush:js;"> document.getElementById('ul').onclick = function(e) { var e = e || window.event,tar = e.target || e.srcElement; if (tar.nodeName.toLowerCase() == 'li') { tar.style.background = 'black'; } }

6)节流与去抖动

节流(throttle):预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期。

例如mousemove 事件、window对象的resize和scroll事件。

去抖动(debounce):当调用动作n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间。

例如文本输入keydown 事件,keyup 事件,做autocomplete等。

节流与去抖动最大的不同的地方就是在计算最后执行间的方式上。著名的开源工具库underscore中有内置了两个方法

在做公司内部的一个系统的时候,需要方希望在左右滚动表格的时候,能将第一列固定在最左边,方便查看。

为了让操作能更流畅,我再这里用了节流,有些浏览器会出现卡顿,就得需要增加周期时间。

三、小技巧

在移动页面的时候经常需要调试字段,又不能用console.log,每次alert的话,碰到对象就看不到内容了。

只能自己写个小方法来打印出来,JSON.stringify,通过这个方法能够方便的实现功能

rush:js;"> var print = function(obj,space) { space = space || 4; var html = JSON.stringify(obj,null,space); html = html.replace(/\n/g,'
').replace(/\s/g,' '); var pre = document.createElement('pre'); var div = document.createElement('code'); pre.style.csstext = 'border:1px solid #000;padding:10px;background:#FFF;margin-bottom:20px;'; div.innerHTML = html; pre.appendChild(div); var body = document.querySelector('body'); body.insertBefore(pre,body.children[0]); };

print({a:1,b:'demo',c:{text:'content'}});

插件JSON-handle

服务器返回的很多都是JSON格式的数据,通常写好后给你个接口,顺便给你几个demo参数。

在浏览器中打开后,就是一串字符串,但要给人看的话,就得格式化一下了,这个插件就是用来让人看的。

原文地址:https://www.jb51.cc/js/42082.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐