<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>前台 on 两点之间</title><link>https://yuehei.37net.com/category/%E5%89%8D%E5%8F%B0/</link><description>Recent content in 前台 on 两点之间</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Mon, 16 Nov 2009 07:51:58 +0000</lastBuildDate><atom:link href="https://yuehei.37net.com/category/%E5%89%8D%E5%8F%B0/index.xml" rel="self" type="application/rss+xml"/><item><title>QQ群前端使用的 javascript loader</title><link>https://yuehei.37net.com/2009/11/qq_javascript_loade/</link><pubDate>Mon, 16 Nov 2009 07:51:58 +0000</pubDate><guid>https://yuehei.37net.com/2009/11/qq_javascript_loade/</guid><description>&lt;p&gt;开始主要想看一下qq群所使用的javascript模板，后来发现他们用的也是一个jquery的插件。&lt;br&gt;
不过这个加载写的也很不错，分析了一下，原JS： &lt;a href="http://qun.qq.com/god/m/js/loader.zh-cn.js" target="_blnak" target="_blank" rel="nofollow" &gt;&lt;a class="link" href="http://qun.qq.com/god/m/js/loader.zh-cn.js" target="_blank" rel="noopener"
 &gt;http://qun.qq.com/god/m/js/loader.zh-cn.js&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;pre lang="javascript"&gt;; (function() {
 var window = this,
 undefined,
 jLoader = window.jLoader = window.jL = {
 _version: "1.2.1",
 _sequence: [],
 _queue: {},
 _xhr: function() {
 return window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
 },
 // 直接加载脚本
 _script: function(uri, context) {
 context = context || document;
 var head = context.getElementsByTagName("head")[0] || context.documentElement,
 script = context.createElement("script");
 script.type = "text/javascript";
 script.src = uri;
 head.appendChild(script);
 return script;
 },
 _style: function(uri, context) {
 context = context || document;
 var head = context.getElementsByTagName("head")[0] || context.documentElement,
 link = context.createElement("link"),
 links = context.getElementsByTagName("link", context);
 link.type = "text/css";
 link.rel = "stylesheet";
 link.href = uri;
 if (0 &amp;lt; links.length) {
 var _last = links[links.length - 1];
 _last.parentNode.insertBefore(_link, _last.nextSibling);
 } else {
 head.appendChild(link);
 }
 return link;
 },
 _replace: function(pattern, uri, context) {
 if (!pattern || !uri) {
 return;
 }
 context = context || document;
 var links = context.getElementsByTagName("link", context);
 for (var i = links.length - 1; i &amp;gt;= 0; i--) {
 if ( - 1 != links[i].href.indexOf(pattern)) {
 links[i].parentNode.removeChild(links[i]);
 }
 }
 if (uri) {
 jLoader._style(uri, context);
 }
 },
 // 将脚本内容插入当前页面来执行
 _globalEval: function(data, context) {
 if (data &amp;&amp; /\S/.test(data)) {
 context = context || document;
 var head = context.getElementsByTagName("head")[0] || context.documentElement,
 script = context.createElement("script");
 script.type = "text/javascript";
 if (jLoader._excute) {
 script.appendChild(context.createTextNode(data));
 } else {
 script.text = data;
 }
 head.insertBefore(script, head.firstChild);
 head.removeChild(script);
 return true;
 }
 return false;
 },
 // 执行回调方法数组。有可能请求多次，绑定了多个的回调方法。
 _call: function(mark) {
 if (jLoader._queue&amp;lt;mark&gt;&amp;lt;/mark&gt;.callbacks) {
 var cl = jLoader._queue&amp;lt;mark&gt;&amp;lt;/mark&gt;.callbacks.length;
 for (var j = 0; j &amp;lt; cl; j++) {
 jLoader._queue&amp;lt;mark&gt;&amp;lt;/mark&gt;.callbacks[j][0](jLoader._queue&amp;lt;mark&gt;&amp;lt;/mark&gt;.callbacks[j][1]);
 }
 }
 },
 // 这是一个顺序加载的过程，每加载一个JS，都会放入sequence队列，如果depend=true,则该脚本之前的脚本全部加载完后该脚本才执行
 _inject: function() {
 var len = jLoader._sequence.length;
 for (var i = 0; i &amp;lt; len; i++) {
 var seq = jLoader._queue[jLoader._sequence[i]];
 if (!seq.done) {
 if (!seq.response) {
 return;
 } else {
 seq.done = true;
 seq.response = [seq.response, ";jLoader._call(\"", jLoader._sequence[i], "\");"].join("");
 jLoader._globalEval(seq.response);
 }
 }
 }
 },
 scripted: function(mark) {
 if ("undefined" == typeof jLoader._queue&amp;lt;mark&gt;&amp;lt;/mark&gt;) {
 return false;
 } else {
 if (jLoader._queue&amp;lt;mark&gt;&amp;lt;/mark&gt;.done) {
 return true;
 } else {
 return false;
 }
 }
 },
 script: function(options) {
 options = options || {};
 // 参数不全
 if (!options.mark || !options.uri)
 return;
 options.depend = options.depend || false;
 options.params = options.params || {};
 options.onload = options.onload || null;
 // 如果没有依赖关系和回调方法，则直接引入
 if (!options.onload &amp;&amp; !options.depend) {
 jLoader._script(options.uri);
 jLoader._queue[options.mark] = {
 uri: options.uri,
 response: null,
 done: true
 };
 return;
 }
 // 是否为第一次请求
 if ("undefined" == typeof jLoader._queue[options.mark]) {
 jLoader._queue[options.mark] = {
 uri: options.uri,
 response: null,
 done: false
 };
 // 设置回调方法和回调的参数
 if ("function" == typeof options.onload) {
 jLoader._queue[options.mark].callbacks = [[options.onload, options.params]];
 }
 } else {
 // 虽然不是第一次请求，但有没有真正加载。没有真正加载的原因此时正在异步请求脚本内容
 if (false == jLoader._queue[options.mark].done) {
 // 如果已经设置为callbacks, 则追加callbacks, 前面设置的callbacks是数组
 if ("function" == typeof options.onload) {
 if ("undefined" == typeof jLoader._queue[options.mark].callbacks) {
 jLoader._queue[options.mark].callbacks = [[options.onload, options.params]];
 } else {
 var cl = jLoader._queue[options.mark].callbacks.length;
 jLoader._queue[options.mark].callbacks[cl] = [options.onload, options.params];
 }
 }
 } else {
 // 已真正加载，直接执行回调方法
 if ("function" == typeof options.onload) {
 options.onload(options.params);
 }
 }
 return;
 }
 // 将脚本按顺序放入队列，self._inject会用到
 var len = jLoader._sequence.length;
 if (options.depend) {
 jLoader._sequence[len] = options.mark;
 }
 var xhr = jLoader._xhr();
 xhr.onreadystatechange = function() {
 if (4 == xhr.readyState) {
 // 如果设置了依赖关系，则检查依赖。如果没有设置，则执行脚本内容和回调函数
 if (options.depend) {
 jLoader._queue[options.mark].response = xhr.responseText;
 jLoader._inject();
 } else {
 jLoader._queue[options.mark].done = true;
 var response = [xhr.responseText, ";jLoader._call(\"", options.mark, "\");"].join("");
 jLoader._globalEval(response);
 }
 }
 };
 xhr.open("GET", options.uri, true);
 xhr.send("");
 }
 };
 // 很好，很强大，因为getTime()结果不一样，所以用这种方法可以准确的定位到某一个类有没有执行
 jLoader._excute = false;
 var root = document.documentElement,
 script = document.createElement("script"),
 id = "script" + (new Date).getTime();
 script.type = "text/javascript";
 try {
 script.appendChild(document.createTextNode("window." + id + "=1;"));
 } catch(e) {}
 root.insertBefore(script, root.firstChild);
 if (window[id]) {
 jLoader._excute = true;
 delete window[id];
 }
 root.removeChild(script);
})();&lt;/pre&gt;</description></item></channel></rss>