javascript
  • jquery
  • 2009-12-10 74 views 5 likes 
    5

    我有一個JavaScript函數我正在寫哪個被用來包含外部JS文件,但只有一次。我需要這樣一個函數的原因是因爲當通過AJAX加載某些內容時它被調用,並且我需要爲該內容運行頁面特定的代碼(不,只是使用.live不會覆蓋它)。動態地包含javascript文件只有一次

    這裏是我的嘗試,縮短爲簡潔:

    $.include_once = function(filename) { 
        if ($("script[src='" + filename + "']").length === 0) { 
         var $node = $("<script></script>") 
          .attr({ 
           src : filename, 
           type : "text/javascript" 
          }) 
         ; 
         $(document.body).append($node); 
        } 
    }; 
    

    這工作正常:函數被調用時,它加載外部文件,以及加載時該文件正在運行。完善。

    問題是,它將始終重新加載該外部文件:我用來檢查腳本的存在的查詢總是找不到任何東西!

    當調試這一點,我添加了一些行:

    alert($("script").length);  // alerts: 4 
    $(document.body).append($node); 
    alert($("script").length);  // alerts: 4 
    

    展望動態源(螢火蟲的HTML標籤),我無法找到腳本標籤都沒有。

    我知道我可以維護一個以前包含的文件數組,但我希望能夠使用像這樣的方法(如果它工作的話),看起來更健壯一些,因爲不是全部JS文件正在以這種方式被包含。

    任何人都可以解釋在這第二個片段中看到的行爲?

    回答

    5

    在這種情況下,jQuery有點愚蠢;它完全不符合你的期望。當你append($node) jQuery這樣做:

    jQuery.ajax({ 
        url: $node.src, 
        async: false, 
        dataType: "script" 
    }) 
    

    Woops!對於本地文件(例如,在同一個域中),jQuery爲.js文件正文執行標準XMLHttpRequest,並且通過創建<script>標記(再次!)和將其設置爲內容的整個複雜過程繼續到「評估」您的.js文件正文。這是模擬eval,但在全球範圍內。

    對於跨域文件,由於由於相同域策略而無法執行標準XMLHttpRequest,jQuery再次創建<script>元素並將其插入到<head>中。

    在本地和跨域情況下,上述的jQuery 最後得到各地這樣做:

    head.removeChild(script); 
    

    而且繁榮.length檢查!遊民。

    因此,對您的問題,不要打擾jQuery與此。只要做

    document.getElementsByTagName('head')[0] 
        .appendChild(
        document.createElement('script') 
    ) 
        .src = filename; 
    

    這將做你所期望的,特別是後來查詢它。

    +0

    優秀的迴應。我認爲jQuery本身或某事太聰明瞭。 – nickf 2009-12-10 03:21:50

    +0

    @nickf:我對jQuery的大部分內容都有這種感覺(太聰明瞭);我猜想有很多必要的惡意。 – 2009-12-10 03:27:34

    3

    您正試圖解決已經解決了多次的問題。例如,嘗試LazyLoad。也有類似的jQuery插件。

    0

    不是設置腳本標記的源屬性,而是設置腳本標記的「text」屬性。這適用於所有現代瀏覽器(我在實踐中使用該應用程序的應用程序不支持IE6,所以我不知道這個蠕變......)。 (實際上它看起來像這樣(你必須添加代碼來省略你自己的雙重包含 - 例如一個簡單的所有已讀取的腳本數組,儘管這是非常特定於應用程序的,爲什麼還要加載代碼兩次?嘗試省略雙加載代碼...):

    var script_source_code_string = <some dynamically loaded script source code>; 
    var $n = $("<script></script>"); 
    $n.get(0).text = script_source_code_string; 
    $(document.body).append($n); 
    

    或者更簡單(沒有的jQuery,我在這個階段代碼不知道jQuery的,它也可以動態加載):

    var script_source_code_string = <some dynamically loaded script source code>; 
    var s = document.createElement('script'); 
    document.getElementsByTagName('head')[0].appendChild(s); 
    s.text = script_source_code_string; 
    
    相關問題