使用lazyload 异步加载css js 文件. 提高页面初始化的速度,减小卡顿时间 , 下面是 使用方法 与 lazyload.js 源码 (中文注释) 调用方法后. 会追加到 head 标签末尾 会按照 数组中的地址顺序 进行加载文件 加载成功后有 console.log().进行日志打印 不须要的话,能够删除. 有兴趣的能够看看注释, 研究一下LazyLoad.js 的 实现方式.
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>test</title> <meta name="Keywords" content=""> <meta name="Description" content=""> <!--先 引入lazyload 再调用方法--> <script src="/js/JsTool/CssJsFileLazyLoad/lazyload.js"></script> <script async="async"> var cssFile = [ '/css/backstage/1.css', '/css/backstage/2.css', '/css/backstage/3.css', '/css/backstage/4.css', '/css/backstage/5.css', '/css/backstage/6.css' ]; //调用方法后. 会追加到 head 标签末尾 //会按照 数组中的顺序 进行加载文件 LazyLoad.css(cssFile, function () { console.log("css加载完成..."); }); </script> </head> <body class="bg_0"> <div>内容</div> <script async="async"> var jsFile = [ '/js/backstage/jquery/1.js', '/js/backstage/jquery/2.js', '/js/backstage/jquery/3.js', '/js/backstage/jquery/4.js', '/js/backstage/jquery/5.js', '/js/backstage/jquery/6.js' ]; //调用方法后. 会追加到 head 标签末尾 LazyLoad.js(jsFile, function () { console.log("js加载完成..."); }); </script> </body> </html>
/** * 异步加载css 与 js 文件 * xue * */ LazyLoad = (function (doc) { /** * 如何使用: * * CSS: * var cssFile = [ '/css/backstage/1.css', '/css/backstage/2.css', '/css/backstage/3.css', '/css/backstage/4.css', '/css/backstage/5.css', '/css/backstage/6.css' ]; //能够使用数组的形式,加载多个css文件. 也能够传入一个字符串,加载一个css LazyLoad.css(cssFile, function () { console.log("css加载完成..."); }); * *JS: var jsFile = [ '/js/backstage/jquery/1.js', '/js/backstage/jquery/2.js', '/js/backstage/jquery/3.js', '/js/backstage/jquery/4.js', '/js/backstage/jquery/5.js', '/js/backstage/jquery/6.js' ]; //能够使用数组的形式,加载多个js文件. 也能够传入一个字符串,加载一个js LazyLoad.js(jsFile, function () { console.log("js加载完成..."); }); */ // Private Property -------------------------------------------------------- var env, head, pending = {}, pollCount = 0, queue = { css: [], js: [] }, styleSheets = doc.styleSheets, startTime, endTime; // Private Methods -------------------------------------------------------- /** 建立并返回具备指定名称和属性的HTML元素。 @method createNode @param {String} name 元素名 @param {Object} attrs 元素属性的 名称/值 映射 @return {HTMLElement} @private */ function createNode(name, attrs) { var node = doc.createElement(name), attr; for (attr in attrs) { if (attrs.hasOwnProperty(attr)) { node.setAttribute(attr, attrs[attr]); } } return node; } /** 当指定类型的当前挂起资源完成时调用装载。执行关联的回调(若是有)并加载下一个回调队列中的资源。 @method finish @param {String} type 资源类型 ('css' or 'js') @private */ function finish(type) { var p = pending[type], callback, urls; if (p) { callback = p.callback; urls = p.urls; urls.shift(); pollCount = 0; // 若是这是最后一个挂起的url,则执行回调和 // 启动队列中的下一个请求(若是有)。 if (!urls.length) { callback && callback.call(p.context, p.obj); pending[type] = null; queue[type].length && load(type); } } } /** 填充 <code>env</code> 变量带有用户代理和特性测试信息。 @method getEnv @private */ function getEnv() { var ua = navigator.userAgent; env = { //若是此浏览器支持动态禁用异步模式,则为True //建立脚本节点 async: doc.createElement('script').async === true }; (env.webkit = /AppleWebKit\//.test(ua)) || (env.ie = /MSIE|Trident/.test(ua)) || (env.opera = /Opera/.test(ua)) || (env.gecko = /Gecko\//.test(ua)) || (env.unknown = true); } /** 加载指定的资源或指定类型的下一个资源 若是没有指定资源,则在队列中。若是指定的资源 类型已加载,新请求将排队,直到 第一个请求已经完成。 当指定资源url数组时,将加载这些url 若是可能的话,在保持执行顺序的同时并行执行。全部 浏览器支持CSS的并行加载,但只支持Firefox和Opera 支持脚本的并行加载。在其余浏览器中,脚本将是 排队并一次加载一个,以确保正确的执行顺序。 @method load @param {String} type 资源类型 ('css' or 'js') @param {String|Array} urls (optional) 要加载的URL或URL数组 @param {Function} callback (optional) 回调函数 @param {Object} obj (optional) 对象传递给回调函数 @param {Object} context (optional) 若是提供,则回调函数将在这个对象的上下文中执行 @private */ function load(type, urls, callback, obj, context) { //开始计时 startTime = new Date().getTime(); var _finish = function () { finish(type); }, isCSS = type === 'css', nodes = [], i, len, node, p, pendingUrls, url; env || getEnv(); if (urls) { //若是url是字符串,则将其包装在数组中。不然假设它是 //数组并建立它的副本,这样就不会对其进行修改 urls = typeof urls === 'string' ? [urls] : urls.concat(); // 为每一个URL建立一个请求对象。若是指定了多个url, // 回调只会在加载全部url以后执行。 // //遗憾的是,Firefox和Opera是惟一可以加载的浏览器 //脚本并行,同时保持执行顺序。在全部其余 //浏览器,脚本必须顺序加载。 // //全部浏览器都根据连接的顺序尊重CSS的特性 // DOM中的元素,而不考虑样式表的顺序 //其实是下载的。 if (isCSS || env.async || env.gecko || env.opera) { // 并行加载 queue[type].push({ urls: urls, callback: callback, obj: obj, context: context }); } else { // 加载顺序。 for (i = 0, len = urls.length; i < len; ++i) { queue[type].push({ urls: [urls[i]], callback: i === len - 1 ? callback : null, // 回调只添加到最后一个URL obj: obj, context: context }); } } } //若是以前的这种类型的加载请求正在进行中,那么咱们将 //轮到咱们了。不然,获取队列中的下一项。 if (pending[type] || !(p = pending[type] = queue[type].shift())) { return; } //获取head标签 head || (head = doc.head || doc.getElementsByTagName('head')[0]); pendingUrls = p.urls.concat(); for (i = 0, len = pendingUrls.length; i < len; ++i) { url = pendingUrls[i]; //开始拼接 标签 if (isCSS) { node = env.gecko ? createNode('style') : createNode('link', { href: url, rel: 'stylesheet' }); } else { node = createNode('script', { src: url }); node.async = false; } node.className = 'lazyload'; node.setAttribute('charset', 'utf-8'); if (env.ie && !isCSS && 'onreadystatechange' in node && !('draggable' in node)) { node.onreadystatechange = function () { if (/loaded|complete/.test(node.readyState)) { node.onreadystatechange = null; _finish(); } }; } else if (isCSS && (env.gecko || env.webkit)) { // Gecko和WebKit不支持连接节点上的onload事件。 if (env.webkit) { //在WebKit中,咱们能够轮询对文档的更改。样式表 //肯定样式表什么时候加载。 p.urls[i] = node.href; //解析相对url(或轮询不起做用) pollWebKit(); } else { //在Gecko中,咱们能够将请求的URL导入到<style>节点中 //轮询node.sheet.cssRules是否存在。 node.innerHTML = '@import "' + url + '";'; pollGecko(node); } } else { node.onload = node.onerror = _finish; } nodes.push(node); } for (i = 0, len = nodes.length; i < len; ++i) { head.appendChild(nodes[i]); //控制台日志部分(不须要能够删除) //start var url = pendingUrls[i]; if (/.js/.exec(url)) { console.log((i + 1) + "--> js成功: " + url); } else if (/.css/.exec(url)) { console.log((i + 1) + "--> css成功: " + url); } else { console.log("error: " + url); } //end } //结束计时 endTime = new Date().getTime(); //控制台日志部分(不须要能够删除) //(startTime (在此方法开头),endTime(在此行代码上方) 均可以删除 ) console.log("执行时间: " + (endTime - startTime) + " ms ------- end时间戳:" + endTime); } /** 开始轮询,以肯定指定的样式表什么时候完成加载 轮询在加载全部挂起的样式表或加载10个样式表以后中止 秒(防止停顿)。 @method pollGecko @param {HTMLElement} node 样式节点。 @private */ function pollGecko(node) { var hasRules; try { //咱们不须要存储这个值,也不须要再次引用它,可是 //若是咱们不存储它,闭包编译器会认为代码是无用的 //删除它。 hasRules = !!node.sheet.cssRules; } catch (ex) { // 异常意味着样式表仍在加载。 pollCount += 1; if (pollCount < 200) { setTimeout(function () { pollGecko(node); }, 50); } else { //咱们已经轮询了10秒钟,什么都没有发生。 //中止轮询并完成挂起的请求,以免进一步阻塞请求。 hasRules && finish('css'); } return; } // 到这里,样式表已经加载。 finish('css'); } /** 开始轮询,以肯定挂起的样式表什么时候完成加载 在WebKit。轮询在加载全部挂起的样式表或加载10个样式表以后中止 秒(防止停顿)。 @method pollWebKit @private */ function pollWebKit() { var css = pending.css, i; if (css) { i = styleSheets.length; // 查找与挂起的URL匹配的样式表。 while (--i >= 0) { if (styleSheets[i].href === css.urls[0]) { finish('css'); break; } } pollCount += 1; if (css) { if (pollCount < 200) { setTimeout(pollWebKit, 50); } else { //咱们已经轮询了10秒钟,什么都没有发生 //表示样式表已从文档中删除 //在它有机会装载以前。中止轮询并完成挂起 //请求以防止阻止进一步的请求。 finish('css'); } } } } // Public Methods -------------------------------------------------------- return { /** 请求指定的CSS URL或URL并执行指定的 当它们完成加载时回调(若是有的话)。若是一个url数组是 指定后,样式表将与回调并行加载 将在全部样式表加载完成后执行。 @method css @param {String|Array} urls CSS URL或要加载的CSS URL数组 @param {Function} callback (optional) 回调函数 @param {Object} obj (optional) 对象传递给回调函数 @param {Object} context (optional) 若是提供,回调函数将在这个对象的上下文中执行吗 @static */ css: function (urls, callback, obj, context) { load('css', urls, callback, obj, context); }, /** 请求指定的JavaScript URL并执行指定的 当它们完成加载时回调(若是有的话)。若是一个url数组是 指定并获得浏览器的支持后,脚本将被加载进来 并将在全部脚本完成后执行回调 完成加载。 目前,只有Firefox和Opera支持同时并行加载脚本 保存执行顺序。在其余浏览器中,脚本将是 排队并一次加载一个,以确保正确的执行顺序 @method js @param {String|Array} urls JS URL或要加载的JS URL数组 @param {Function} callback (optional) 回调函数 @param {Object} obj (optional) 对象传递给回调函数 @param {Object} context (optional) 若是提供,回调函数将在这个对象的上下文中执行吗 @static */ js: function (urls, callback, obj, context) { load('js', urls, callback, obj, context); } }; })(this.document);