/**
* @preserve Tiny-Loader: A small loader that load CSS/JS in best way for page performanceIs.
*
* @version 1.0.1
* @copyright The Youzan Limited [All Rights Reserved]
* @license MIT License (see LICENSE.txt)
*/
(function(window, document) {
'use strict';
// cssExpr 用於判斷資源是不是css
var cssExpr = new RegExp('\\.css');
var nHead = document.head || document.getElementsByTagName('head')[0];
// `onload` 在WebKit < 535.23, Firefox < 9.0 不被支持
var isOldWebKit = +navigator.userAgent
.replace(/.*(?:AppleWebKit|AndroidWebKit)\/?(\d+).*/i, '$1') < 536;css
// 判斷對應的node節點是否已經載入完成
function isReady(node) {
return node.readyState === 'complete' || node.readyState === 'loaded';
}node
// loadCss 用於載入css資源
function loadCss(url, setting, callback) {
var node = document.createElement('link');jquery
node.rel = 'stylesheet';
addOnload(node, callback, 'css');
node.async = true;
node.href = url;web
nHead.appendChild(node);
}數組
// loadJs 用於載入js資源
function loadJs(url, setting, callback) {
var node = document.createElement('script');app
node.charset = 'utf-8';
addOnload(node, callback, 'js');
node.async = !setting.sync;
node.src = url;異步
nHead.appendChild(node);
}async
// 在老的webkit中,因不支持load事件,這裏用輪詢sheet來保證
function pollCss(node, callback) {
var isLoaded;函數
if (node.sheet) {
isLoaded = true;
}url
setTimeout(function() {
if (isLoaded) {
// 在這裏callback 是爲了讓樣式有足夠的時間渲染
callback();
} else {
pollCss(node, callback);
}
}, 20);
}
// 用於給指定的節點綁定onload回調
// 監聽元素載入完成事件
function addOnload(node, callback, type) {
var supportOnload = 'onload' in node;
var isCSS = type === 'css';
// 對老的webkit和老的firefox的兼容
if (isCSS && (isOldWebKit || !supportOnload)) {
setTimeout(function() {
pollCss(node, callback);
}, 1);
return;
}
if (supportOnload) {
node.onload = onload;
node.onerror = function() {
node.onerror = null;
window._cdnFallback(node);
};
} else {
node.onreadystatechange = function() {
if (isReady(node)) {
onload();
}
};
}
function onload() {
// 執行一次後清除,防止重複執行
node.onload = node.onreadystatechange = null;
node = null;
callback();
}
}
// 資源下載入口,根絕文件類型的不一樣,調用loadCss或者loadJs
function loadItem(url, list, setting, callback) {
// 若是加載的url爲空,就直接成功返回
if (!url) {
setTimeout(function() {
onFinishLoading();
});
return;
}
if (cssExpr.test(url)) {
loadCss(url, setting, onFinishLoading);
} else {
loadJs(url, setting, onFinishLoading);
}
// 每次資源下載完成後,檢驗是否結束整個list下載過程
// 若已經完成全部下載,執行回調函數
function onFinishLoading() {
var urlIndex = list.indexOf(url);
if (urlIndex > -1) {
list.splice(urlIndex, 1);
}
if (list.length === 0) {
callback();
}
}
}
function doInit(list, setting, callback) {
var cb = function() {
callback && callback();
};
list = Array.prototype.slice.call(list || []);
if (list.length === 0) {
cb();
return;
}
for (var i = 0, len = list.length; i < len; i++) {
loadItem(list[i], list, setting, cb);
}
}
// 判斷當前頁面是否加載完
// 加載完,馬上執行下載
// 未加載完,等待頁面load事件之後再進行下載
function ready(node, callback) {
if (isReady(node)) {
callback();
} else {
// 1500ms 之後,直接開始下載資源文件,再也不等待load事件
var timeLeft = 1500;
var isExecute = false;
window.addEventListener('load', function() {
if (!isExecute) {
callback();
isExecute = true;
}
});
setTimeout(function() {
if (!isExecute) {
callback();
isExecute = true;
}
}, timeLeft);
}
}
// 暴露出去的Loader
// 提供async, sync兩個函數
// async 用做異步下載執行用,不阻塞頁面渲染
// sync 用做異步下載,順序執行,保證下載的js按照數組順序執行
var Loader = {
async: function(list, callback) {
ready(document, function() {
doInit(list, {}, callback);
});
},
sync: function(list, callback) {
ready(document, function() {
doInit(list, {
sync: true
}, callback);
});
}
};
window.Loader = Loader;
return Loader;
})(window, document);
例如:
var list = ["../../static/common/js/util/jquery-1.9.1.min.js","../../static/common/js/util/template.js"]Loader.async(list,function(){ alert("111");});