LMLJS, 为更少的等待而生!
LMLJS 是一款可爱滴 JavaScript 框架, 内置 Deferred 对象,实现网页图片可视区域加载,异步加载 Js 等静态资源,异步加载 HTML 中 Iframe,异步加载 CSS 样式中图片,让网页以最快的速度 onLoad,让用户在最短的时间内看到网页内容,遵循 MIT 开源协议。
如何获取 LMLJS?
LMLJS 项目地址:https://github.com/leiminglin/LMLJS。将 lml.js 文件中的代码拷贝到网站的 HEAD 标签中的 SCRIPT 标签里面,这么做只是为了让 LMLJS 在所有 JS 前执行。不建议将 LMLJS 单独放在一个 .js 文件中,这样浏览器需要发出一次请求获取 LMLJS,违背了 LMLJS 设计的初衷 - 为更少的等待而生。
启动 LMLJS
LMLJS 启动非常简单。如下代码所示:
<script> window.onload = function(){ lml.run(); }; </script>
异步执行 JavaScript 脚本
在页面中,如果需要执行 JavaScript 代码,若 执行过程可能比较耗时,比如需要发出请求等,可以将代码放到 LMLJS 的 then 方法中,待网页完全加载后再执行。如下代码所示:
<script> lml.deferred.then(function(){ /* do something here */ lml.deferred.promise(); }); </script>
异步 CSS
异步 CSS 是指异步加载 CSS 中的图片。若网页中的 CSS 含有背景图片需要发出请求,可以使用 LMLJS 提供的 lazyCss 功能,将 CSS 内容用 textarea 包裹起来,让图片在页面渲染完成后发出请求。也可以使用其他标签包裹,只要 class 属性里面含有 lazyCss 即可。为了让 TEXTAREA 不被显示出来,需要加上一个 hidden 样式隐藏掉,下文中的 hidden 都代表这个意思。如下代码所示:
<textarea class="lazyCss hidden"> .sitebg{ background:url(/static/bg.jpg); } </textarea>
异步 HTML
异步 HTML 是指异步加载 HTML 中的 Iframe JavaScript 等。若网页中需要嵌入视频或者其他的页面,这样的内容可能会拖慢网页的渲染速度,这种情况下可以使用 LMLJS 提供的 lazyHtml 功能实现异步渲染部分 HTML,异步加载的 HTML 必须要用 TEXTAREA 包裹。如下代码所示:
<textarea class="lazyHtml hidden"> <iframe height=300 width="90%" src="http://player.youku.com/embed/XODUzNzcwMzg4" frameborder=0 allowfullscreen> </iframe> </textarea>
下面的视频是使用 LMLJS 异步加载的。
加载 JavaScript 文件
使用了 LMLJS 后,不建议页面的源代码中直接使用 SCRIPT 标签引入外部 JS 资源,可以使用 LMLJS 提供的 loadJs 方法进行加载,需要注意的是:为了兼容 1.0 版本, loadJs 的默认回调函数仍然是 deferred.promise(); ,但建议传递一个回调,如果没有就传递空函数,如果需要加载的 JavaScript 文件中含有依赖关系,可以传入数组实现依次加载,1.1 版本增加了 competeLoad() 方法实现竞争加载,应用场景为:当项目中使用了很多的 JS CDN 服务商,可以使用此方法达到最快的加载效果,此方法适用于加载相同的 JS 文件。如下代码所示:
<script> /* 普通加载 */ lml.loadJs(js_src); lml.loadJs(js_src2, callback); /* 依次加载 js_src 和 js_src2 */ lml.loadJs([js_src, js_src2], function(){}); /* 竞争加载 js_src 和 js_src2 */ lml.loadJs.competeLoad([js_src, js_src2], function(){ /* callback */ }); /* loadJs 方法无需放在 deferred 的 then 方法中,在页面 DOMContentLoaded 后才会开始自动加载*/ </script>
loadJs 方法的第三个参数可以不传递,传入 1 代表强制加载,强制加载的意思就是如果页面已经加载了某个 JS 文件,仍然会再次请求这个 JS 文件;如果不传递,已经加载过的 JS 文件不再加载,也就是 DOM 节点中不会出现两个一样的 JS 标签,然后直接执行回调函数。
创建 Deferred 对象
若网页中有很多异步任务,且任务的优先级顺序比较复杂,通过 LMLJS 默认提供的一个 deferred 对象还不能够满足的情况下,可以使用 createDeferred 方法创建一个新的 deferred 对象嵌套在 then 方法中,来实现更复杂的异步执行流。上面的例子实现 JS 文件的依次加载同样也可以通过创建新的 deferred 对象来实现,事实上已经无需这样做了。如下代码所示:
<script> lml.deferred.then(function(){ var deferred2 = lml.createDeferred(); deferred2.then(function(){ /* deferred2 对象异步执行流 */ }); lml.deferred.promise(); deferred2.promise(); }); window.onload = function(){ lml.deferred.promise(); }; </script>
可视区域图片异步加载
LMLJS 内置了可视区域异步加载图片功能,当页面在滚动的过程中,图片标签出现在可视区域范围内,则开始加载图片资源,防止在页面中图片很多的情况下页面渲染太慢,同时也减少了服务器压力,避免了不必要的流量浪费。要实现图片在可见范围加载,需要将图片的 src 属性改为 osrc 属性,另外可以附加上一个 osrc-bak 属性作为备份图片,备份图片仅在图片加载失败后尝试的补救措施。如下代码所示:
<img width="635" height="476" osrc="http://git.oschina.net/leiminglin/images/raw/master/2014/12/IMG_20141224_122726.jpg" osrc-bak="https://raw.githubusercontent.com/leiminglin/images/master/2014/12/IMG_20141224_122726.jpg" alt="世纪大道午后时光-LMLPHP后院" title="世纪大道午后时光-LMLPHP后院" />
下面的图片需要在可见范围内才会被加载。