javascript中動態加載js文件多種解決辦法

  1.  var head = document.head  
  2.               || document.getElementsByTagName("head")[0]|| document.documentElement;  
  3.    var script = document.createElement("script");  
  4.    script.setAttribute("type","text/javascript");  
  5.    script.setAttribute("src",url);  
  6.    //////////////////////////好像只有IE支持  
  7.    script.onreadystatechange=function(){  
  8.    if(document.readyState=='complete'){  
  9.           callback();  
  10.        }  
  11.      };  
  12.    / //////////  
  13.    head.insertBefore(script, head.firstChild);  

        這種方式就是創建一個script對象,在設置script的src屬性,這種方式最簡單。但是上邊利用加載狀態來處理,他的兼容不是很好。


  其實這裏把open裏面設置爲false就是同步加載了,同步加載不需要設置onreadystatechange事件。

方法六:XMLHttpRequest/ActiveXObject同步加載  

  在這裏我把一些情況考慮在內,寫成了一個方法,封裝爲loadJS.js,方便以後直接調用,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/**
 * 同步加載js腳本
 * @param id   需要設置的<script>標籤的id
 * @param url   js文件的相對路徑或絕對路徑
 * @return {Boolean}   返回是否加載成功,true代表成功,false代表失敗
 */
function loadJS(id,url){
    var  xmlHttp = null;
    if(window.ActiveXObject)//IE
    {
        try {
            //IE6以及以後版本中可以使用
            xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch (e) {
            //IE5.5以及以後版本可以使用
            xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
    }
    else if(window.XMLHttpRequest)//Firefox,Opera 8.0+,Safari,Chrome
    {
        xmlHttp = new XMLHttpRequest();
    }
    //採用同步加載
    xmlHttp.open("GET",url,false);
    //發送同步請求,如果瀏覽器爲Chrome或Opera,必須發佈後才能運行,不然會報錯
    xmlHttp.send(null);
    //4代表數據發送完畢
    if ( xmlHttp.readyState == 4 )
    {
        //0爲訪問的本地,200到300代表訪問服務器成功,304代表沒做修改訪問的是緩存
        if((xmlHttp.status >= 200 && xmlHttp.status <300) || xmlHttp.status == 0 || xmlHttp.status == 304)
        {
            var myHead = document.getElementsByTagName("HEAD").item(0);
            var myScript = document.createElement( "script" );
            myScript.language = "javascript";
            myScript.type = "text/javascript";
            myScript.id = id;
            try{
                //IE8以及以下不支持這種方式,需要通過text屬性來設置
                myScript.appendChild(document.createTextNode(xmlHttp.responseText));
            }
            catch (ex){
                myScript.text = xmlHttp.responseText;
            }
            myHead.appendChild( myScript );
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        return false;
    }
}

        此處考慮到了瀏覽器的兼容性以及當爲Chrome、Opera時必須是發佈,註釋還是寫的比較清楚的,以後需要加載某個js文件時,只需要一句話就行了,如loadJS("myJS","package.js")。方便實用。

  如果想要實現不發佈還非要兼容所有瀏覽器,至少我還沒找出這樣的同步加載的辦法,我們只能通過異步加載開出回調函數來實現。

方法七:回調函數方式

  在同一個文件夾下面創建一個function7.html,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<html>
<head>
    <title>動態加載js</title>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <script type="text/javascript">
        function init()
        {
            //加載package.js文件,設置script的id爲yy
            loadJs("yy","package.js",callbackFunction);
 
        }
        function callbackFunction()
        {
            functionOne();
        }
        function loadJs(sid,jsurl,callback){
            var nodeHead = document.getElementsByTagName('head')[0];
            var nodeScript = null;
            if(document.getElementById(sid) == null){
                nodeScript = document.createElement('script');
                nodeScript.setAttribute('type', 'text/javascript');
                nodeScript.setAttribute('src', jsurl);
                nodeScript.setAttribute('id',sid);
                if (callback != null) {
                    nodeScript.onload = nodeScript.onreadystatechange = function(){
                        if (nodeScript.ready) {
                            return false;
                        }
                        if (!nodeScript.readyState || nodeScript.readyState == "loaded" || nodeScript.readyState == 'complete') {
                            nodeScript.ready = true;
                            callback();
                        }
                    };
                }
                nodeHead.appendChild(nodeScript);
            } else {
                if(callback != null){
                    callback();
                }
            }
        }
    </script>
</head>
<body>
    <input type="button" value="測試按鈕" onclick="init()"/>
</body>
</html>

jQuery.ajax({
    url : src,
    type : "GET",
    dataType : "script",
    async : false,
    global : false,
    "throws" true
});

var src = '3.js';
var xhr = new window.XMLHttpRequest();
xhr.open('GET',src,false);
xhr.send(null);
var responseText = xhr.responseText;
function globalEval(data){
    window["eval"].call(window, data);
}
globalEval(responseText);
//var $a = aa();

var JSLoader = {
    browser : {
        ie : /msie/.test(window.navigator.userAgent.toLowerCase()),
        moz : /gecko/.test(window.navigator.userAgent.toLowerCase()),
        opera : /opera/.test(window.navigator.userAgent.toLowerCase()),
        safari : /safari/.test(window.navigator.userAgent.toLowerCase())
    },
    call : (function() {
        var _file_array = new Array();//保存已添加的文件
        /**
         * 判斷文件是否存在
         * @param tag 元素名稱
         * @param url 文件url
         * @return 如果存在,返回true;否則,返回false
         */
        function hasFile(tag, url) {
            var contains = false;
            var files = document.getElementsByTagName(tag);
            var type = tag == "script" "src" "href";
            for var i = 0, len = files.length; i < len; i++) {
                if (files[i].getAttribute(type) == url) {
                    contains = true;
                    break;
                }
            }
            for(var i=0,len=_file_array.length;i<len;i++){
                if(url==_file_array[i]){
                    contains = true;
                    break;
                }
            }
            return contains;
        }
        /**
         * 串行加載所有js文件
         * 如果所加載的js文件不存在頁面中,則js文件一個接一個加載完成只至最後一個js文件加載完成後,執行回調函數
         * 如果所加載的js文件已經加載過,則直接執行回調函數。
         * @param scripts:['jsFile']
         * @param callback:回調函數[可選]
         * @paren parent:js文件加載的位置,默認爲head
         */
        function serielLoadScripts(scripts, callback,parent) {
            removeExist(scripts);
            if(scripts.length==0){
                if(callback) callback();
                return;
            }
            parent = parent || 'head';
            var head = document.getElementsByTagName(parent)[0]
                    || document.documentElement;
            var s = new Array();
            var last = scripts.length - 1;
            var recursiveLoad = function(i) { // 遞歸
                if(!hasFile("script", scripts[i])){
                    s[i] = document.createElement("script");
                    s[i].setAttribute("type""text/javascript");
                    s[i].onload = s[i].onreadystatechange = function() {
                        if (!JSLoader.browser.ie || this.readyState == "loaded"
                                || this.readyState == "complete") {
                            this.onload = this.onreadystatechange = null;
                            this.parentNode.removeChild(this);
                            if (i != last)
                                recursiveLoad(i + 1);
                            else if (typeof (callback) == "function")
                                callback();
                        }
                    };
                    s[i].setAttribute("src", scripts[i]);
                    head.appendChild(s[i]);
                }else{
                    if(callback){
                        callback();
                    }
                }
            };
            recursiveLoad(0);
        }
        /**
         * 同步加載JS文件
         * 如果所加載的js文件不存在頁面中,則將在所有js文件加載完成以後才執行回調函數。
         * 如果所加載的js文件已經加載過,則直接執行回調函數。
         * @param scripts:['jsFile']
         * @param callback:回調函數[可選]
         */
        function parallelLoadScripts(scripts, callback,parent) {
            removeExist(scripts);
            if(scripts.length==0){
                if(callback) callback();
                return;
            }
            parent = parent || 'head';
            var head = document.getElementsByTagName(parent)[0]|| document.documentElement;
            var s = new Array();
            var loaded = 0;
            for var i = 0; i < scripts.length; i++) {
                if(!hasFile("script", scripts[i])){
                    s[i] = document.createElement("script");
                    s[i].setAttribute("type""text/javascript");
                    s[i].setAttribute("src", scripts[i]);
                    s[i].onload = s[i].onreadystatechange = function() {
                        if (!JSLoader.browser.ie || this.readyState == "loaded"
                                || this.readyState == "complete") {
                            loaded++;
                            this.onload = this.onreadystatechange = null;
                            this.parentNode.removeChild(this);
                            if (loaded == scripts.length&& typeof (callback) == "function"){
                                callback();
                            }
                        }
                    };
                    head.appendChild(s[i]);
                    _file_array.push(scripts[i]);
                }
            }
        }
         
        function cssLoad(csses,callback){
            removeExist(csses);
            if(csses.length==0&&callback){
                callback();
                return;
            }
            var head = document.getElementsByTagName('head')[0]|| document.documentElement;
            var s = new Array();
            var loaded = 0;
            for var i = 0; i < csses.length; i++) {
                if (!hasFile("css", csses[i])) {
                    s[i] = document.createElement("link");
                    s[i].setAttribute("type""text/css");
                    s[i].setAttribute('rel''stylesheet');
                    s[i].setAttribute('href', csses[i]);
                    s[i].onload = s[i].onreadystatechange = function() {
                        if (!JSLoader.browser.ie || this.readyState == "loaded"
                                || this.readyState == "complete") {
                            loaded++;
                            this.onload = this.onreadystatechange = null;
                            if (loaded == scripts.length
                                    && typeof (callback) == "function") {
                                callback();
                            }
                        }
                    };
                    head.appendChild(s[i]);
                    _file_array.push(csses[i]);
                }
            }
        }
         
        function removeExist(arr){
            for(var i=0,len=arr.length;i<len;i++){
                for(var k=0,len_k=_file_array.length;k<len_k;k++){
                    if(arr[i]==_file_array[k]){
                        arr.splice(i,1);
                    }
                }
            }
        }
         
        return {
            seriel : serielLoadScripts,
            paralle : parallelLoadScripts,
            css:cssLoad
        };
    })()
};
/**
 * JS動態導入,外部調用接口
 
 * 注意:爲了保證動態引入的js文件中的事件能夠被正常執行,
 *         請將需要執行事件的動作放入回調函數中執行
 
 * 以jquery爲例:
 * 在點擊菜單A時,動態引入js文件a.js,b.js,並且生成一個按鈕Btn,Btn的onclick事件函數show()位於a.js中。
 * 代碼如下:
 * $(A).click(function(){
 *         jsLoader(['a.js','b.js'],function(){
 *             $('<input type="button" value="測試" onclick="show()">').appendTo($(A));
 *         });           
 * });
 
 * 也可以只是純粹的引入js。這種情況可能會出現問題。
 * 原因:js文件還未加載完成就使用其中的函數或者變量。
 * 改寫上面例子,代碼如下:
 * $(A).click(function(){
 *         jsLoader(['a.js','b.js']);           
 * });
 * $('<input type="button" value="測試" onclick="show()">').appendTo($(A));
 * 這樣寫的話,可能會出現show()未定義,解決方法未找到
 */
var jsLoader = function(scripts,callback,parent,type){
    type = type || "parallel";//默認爲並行模式
    if(type=="seriel"){
        JSLoader.call.seriel(scripts,callback,parent);
    }else{
        JSLoader.call.paralle(scripts,callback,parent);
    }
};
/**
 * CSS動態導入,外部調用接口
 */
var cssLoader = function(csses,callback){
    JSLoader.call.css(csses,callback);
};


var rootObject=document.getElementById("divId");
     var oScript = document.createElement( "script" );
     oScript.type = "text/javascript"; 
     oScript.src = test.js; //test.js方法中有一個方法function test(){alert("test");}
     rootObject.appendChild(oScript); 




如何動態移除js的引用

引用文件時賦予ID 使用jquery刪除 即可 $(id).remove();
刪除文件引用並沒什麼用
建議刪除文件引用後 要釋放該引用文件產生內存

$("script[src='http://www.baidu.com/haha.js']").remove()


在一個JS文件中引用另一個JS文件 
注意:在html文件導入a.js時,應該把script></script寫在/body>後面,否則 document.write()方法有問題。在載入頁面後,瀏覽器輸出流自動關閉;在此之後,任何一個對當前頁面進行操作的 document.write()方法將打開—個新的輸出流。它將清除當前頁面內容(包括源文檔的任何變量或值),因此,假如希望用腳本生成的HTML替換當前頁面,就必須把HTML內容連接起來賦給一個變量、使用一個document.write()方法完成寫操作,不必清除文檔並打開一個新數據流,一 個document.write()調用就可完成所有的操作。
關於document.write()方法還有一點要說明的是它的相關方法document.close()。腳本向窗口(不管是本窗口或其他窗口)寫完內容後.必須關閉輸出流。在延時腳本的最後一個document.write()方法後面.必須確保含有document.close()方法,不這樣做就不能顯示圖片和表單。並且,任何後面調用的document.write()方法只會把內容追加到頁面後,而不會清除現有內容來寫入新值。
在當前JS文件中加入:
document.write("script language='javascript' src='js/jquery-1.3.1.min.js'></script");
 
例如:在a.js中要引用b.js的函數
a.js內容如下:
document.write("script language='javascript' src='b.js'></script");
function test()
{
    b();
}
 
b.js內容如下:
function b()
{
    alert("b");
}
***********************************************************
在處理較爲複雜的頁面邏輯時可能用到多個js文件,比如將實現特定功能的js文件分開放在不同的文件裏面,但是我又不希望在頁面引用時多個js文件,所以就考慮在一個js文件裏面引用另一個js文件了。
具體實現:
HTML文件:
html>
<body>
<input type="button" value="ok" onclick="javascript:b()">
</body>
<!--這裏引用要放在body下面-->
<script language="JAVASCRIPT" src='b.js'>
</script>
</html

b.js代碼: 程序代碼
new_element=document_createElement_x_x_x_x_x("script");
new_element.setAttribute("type","text/javascript");
new_element.setAttribute("src","a.js");
document.body.a(new_element);
function b()
{ a();}
a.js代碼: 程序代碼
function a()
{ alert("a");}


另外例子
<script>
var obj=document.getElementByIdx_x_x_x("某控件");
var ele=document_createElement_x_x_x("script");
ele.src="路徑";
obj.a(ele);


一個比較全部在動態加方法

/*
    動態加載js v1.0 by:dum 2012-03-17 www.hzhuti.com
    用法:src="webJsBase.js?load=a,b"
    注:加載本目錄下js
*/
var webJsBase = {
    require: function(libraryName) {
        document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
    },
    load: function(defaultLoad) {
        if((typeof Prototype=='undefined')||(typeof Element == 'undefined')||(typeof Element.Methods=='undefined'))
        throw ('prototype lib 加載失敗!');
        if(typeof defaultLoad=='undefined')defaultLoad='';
        var js = /webJsBase.js(?.*)?$/;
        $$('head script[src]').findAll(function(s) {
            return s.src.match(js);
        }).each(function(s) {
            var path = s.src.replace(js, '');
            var includes = s.src.match(/?.*load=([a-zA-Z0-9_,]*)/);
            (includes ? includes[1] : defaultLoad).split(',').each(function(include) {
                webJsBase.require(path + include + '.js');
            });
        });
    }
};
 

webJsBase.load(); //這裏參數可以指定默認要加載的js文件

這是最簡單的方法在加載完後再利用直接document.write 如下圖。

<script language="javascript">

    document.write("<script src='test.js'></script>");

</script>
 

給script加個id再去動態改變已有script的src 屬性

 代碼如下 複製代碼
<script src='' id="s1"></script>

<script language="javascript">

    s1.src="test.js"

</script>
 

這裏利用getElementsByTagName('HEAD')動態創建 script元素

 
<script>

    var oHead = document.getElementsByTagName('HEAD').item(0);

    var oScript= document.createElement("script");

    oScript.type = "text/javascript";

    oScript.src="test.js";

    oHead.appendChild( oScript);

</script>
 

還可以這樣嘗試一下,自定一個函數

 


function include(src) {
HTMLCode = '<script language="javascript" src="' + src + '"></script>';
document.write(HTMLCode);
}

調用方法,這樣看上去就你php的include函數了

 代碼如下 複製代碼

include(baseDir + "/Prototype.js");
include(baseDir + "/Map.js");
include(baseDir + "/MapEvent.js");

include(baseDir + "/model/MapModel.js");
include(baseDir + "/model/MapType.js");
include(baseDir + "/model/Tile.js");
 

還有朋友說可以使用ExtJs4 動態加載js這裏我就不介紹了,上面的方法足夠讓你實現動態加載js了.

所以在採用這類方法動態加載Js 的同時,主界面的Js腳本是繼續執行的,所以可能出現通過異步加載的Js代碼得不到預期的效果的情況。

這時候可以考慮採用Ajax加載Js的方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章