使用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);