<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml xml:lang="zh">
<head>
<meta http-equiv="Content-Type" content="text/vnd.wap.wml; charset=utf-8"/>
<meta http-equiv="Cache-Control" content="no-cache"/></head>
<card title="YUI 读码日记之 YAHOO.util.Get - Gracecode.com">
<p>首先要道个歉，距离<a href="http://www.gracecode.com/Archive/Display/1053" title="http://www.gracecode.com/Archive/Display/1053">上次</a>的“YUI 读码日记” 更新已经差不多快两个月了。期间可能是工作忙（这算不上是借口），或者是其他事情给耽误了，但无论如何作为名 YUI 的初学者还是要继续坚持下去的。</p>

<p>上次的 <a href="http://www.gracecode.com/Archive/Display/1307" title="http://www.gracecode.com/Archive/Display/1307">跨域调用</a> 问题，最后使用 YAHOO.util.Get 这个组件搞定的。而接下来的几次开发中，也用到了这个组件，所以激起了对其原理窥探的好奇心。</p>

<pre>YAHOO.util.Get = function() {
    script: function(url, opts) {
        return _queue(&quot;script&quot;, url, opts);
    },

    css: function(url, opts) {
        return _queue(&quot;css&quot;, url, opts); 
    }
}</pre><p>YAHOO.util.Get 的外部调用只有另个方法，分别载入 Javascript 脚本以及 CSS 样式。究其代码，可以很明显的看到其使用了“队列”机制。</p>

<p>下面详细产看此函数的实现。比较点睛的是清理队列，以及加入 lang.later 两点。</p>

<pre>var _queue = function(type, url, opts) {
    var id = &quot;q&quot; + (qidx++);
    opts = opts || {};

    // 当队列到达一定数量时，清理队列（清除已经操作完毕，或者重复的节点）
    //     YAHOO.util.Get.PURGE_THRESH 默认为 20
    if (qidx % YAHOO.util.Get.PURGE_THRESH === 0) {
        _autoPurge();
    }

    // 合并对象，并插入队列
    queues[id] = lang.merge(opts, {
        tId: id,
        type: type,
        url: url,
        finished: false,
        nodes: []
    });

    var q = queues[id];
    q.win = q.win || window;
    q.scope = q.scope || q.win;
    q.autopurge = (&quot;autopurge&quot; in q) ? q.autopurge : 
                  (type === &quot;script&quot;) ? true : false;

    // 请考虑为什么使用 later 并延时为 0
    lang.later(0, q, _next, id);

    return {
        tId: id
    };
};</pre><p>加入外部 CSS 样式，以及 Javascript 的原理非常简单。流程就是使用 createElement 生成节点，然后加入相应的属性，最后插入到文档（document）中（YAHOO.util.Get 是插入到 head 元素中）。</p>

<p>下面看下 YAHOO.util.Get 是如何对元素属性操作的。</p>

<pre>var _node = function(type, attr, win) {
    var w = win || window, d = w.document, n = d.createElement(type);

    for (var i in attr) {
        // 判断有其自身的属性，才确定设置
        if (attr[i] &amp;&amp; YAHOO.lang.hasOwnProperty(attr, i)) {
            n.setAttribute(i, attr[i]);
        }
    }

    return n;
};

var _linkNode = function(url, win) {
    return _node(&quot;link&quot;, {
            &quot;id&quot;: &quot;yui__dyn_&quot; + (nidx++),
            &quot;type&quot;: &quot;text/css&quot;,
            &quot;rel&quot;: &quot;stylesheet&quot;,
            &quot;href&quot;: url
        }, win);
};</pre><p>最后，“精简版”的 getScript 可以这样实现。</p>

<pre>var getScript = function (url) {
    var element  = document.createElement('script');
    element.type = 'text/javascript';
    element.src  = escape(url);
    document.getElementsByTagName(&quot;head&quot;)[0].appendChild(element);   
}</pre><p>当然，适用性自然不及 YAHOO.util.Get 来得好。</p>


<p>
<a href="http://www.gracecode.com/wap/">Gracecode.com</a> |
<a href="http://www.gracecode.com/wap/d/1446 ">Permalink</a>(<a href="http://www.gracecode.com/Archive/Display/1446 ">xHTML</a>) |
<a href="http://www.gracecode.com/Trackback/Recieve/1446/kj4gz4">Trackback</a> |
<a href="http://rss.gracecode.com">Rss</a>
</p>
</card>
</wml>