1. 程式人生 > >Eval函式解決字串JS在IE下不執行的問題

Eval函式解決字串JS在IE下不執行的問題

今天對專案進行測試的時候發現一個很有趣的問題,跟大家分享下。首先說下做的是個什麼樣的功能,廢話不多說上圖:
這裡寫圖片描述
這是一個簡單的表單資料
這裡寫圖片描述
從第二章圖片可以看出來,這個實體是可以在一個頁面新增多個的。
對於一個頁面新增多條資料,以及對資料的處理,後臺程式碼等功能都比較簡單,這裡我就直接跳過。下面說說我遇到的問題:
我在做圖片上傳的時候,每一個圖片的div裡面初始化了一段JS,在第二個用JS輸出的表單裡面同樣的用字串拼接了一段JS,下面是頁面顯示的原始碼
這裡寫圖片描述
下面是我用JS輸出的程式碼

var uploadHtml = ""+
    "<div id=\"mian_"+catalog+"
_"+index+"\" class=\"upload_main_div\">"+ "<div id=\"show_"+catalog+"_"+index+"\" class=\"fileInputContainer\">"+ "<input id=\"attach_object_id\" name=\""+catalog+""+index+"\" value=\""+token+"\" type=\"hidden\">"+ "<div id=\"_att_files_null_"+catalog+"_"+index+"\"></div><script src=\"
/apps/attach/upload.js.jsp\"></script>"+ "<script>var uploader"+uploaderNum+" = new FileUpload('"+message+"',750,400,'"+catalog+"','add','jpg,png,bmp,gif');"+ "uploader"+uploaderNum+".objectId='"+token+"'; uploader"+uploaderNum+".container='_att_files_null_"+catalog+"_"+index+"';" + "uploader"
+uploaderNum+".show();"+ "uploaderNumArray"+catalog+"[index-1] = uploader"+uploaderNum+";" + "$(\"#_att_files_null_"+catalog+"_"+index+"\").bind('DOMNodeInserted', function(e) {"+ "var content = $(e.target).html();"+ "if(content.indexOf(\"img\")!=-1){"+ "$(this).attr(\"class\",\"show_image\");"+ "$(\"#show_"+catalog+"_"+index+">a\").html();"+ "$(\"#show_"+catalog+"_"+index+">a\").hide();"+ "}"+ "});"+ "$(\"#_att_files_null_"+catalog+"_"+index+"\").bind('DOMNodeRemoved', function(e) {"+ "var content = $(e.target).html();"+ "if(content.indexOf(\"img\")!=-1){"+ "$(\"#show_"+catalog+"_"+index+">a\").show();"+ "}"+ "});</script>"; "<a title=\""+message+"\" onclick=\"uploadShow("+index+","+j+")\" class=\"js-button button-icon-upload fileInput\"><span class=\"icon-upload\">&nbsp;</span><span class=\"js-button-text\">"+message+"</span></a>"+ "</div><div class=\"upload_message_div\">上傳"+message+"<br></br></div></div>";

這段程式碼裡面包含了上傳圖片的JS程式碼,這個思路很正常,頁面上輸出正常,火狐谷歌等瀏覽器也執行沒問題,當我完成這一步的時候,我也覺得OK了。但是萬惡的IE瀏覽器卻不識別有字串拼接輸出的JS程式碼。怎麼辦呢?

第一個想法:直接把JS程式碼提出來寫,不拼接成字串。如果細心的會發現,我定義的JS物件的物件名是一個變數,也就是說我定義的這個物件叫什麼是不確定的,不確定也就代表我不能提前定義好。所以這個思路Kill。

第二個想法:變數名拼接變數名,JS可以實現,但是得用window物件轉換好幾次,太複雜。如果是寫在JSP頁面,可以通過如下方式解決:

var upload<%=new Random().nextInt(1000)%> = new FileUpload();

但是因為程式碼的呼叫和載入問題,只能寫在JS檔案中,所以這個思路kill

那麼用什麼方法來解決呢,同事無意直接給我說了一個js函式eval();
首先來說下eval函式:
該方法只接受原始字串作為引數,如果 string 引數不是原始字串,那麼該方法將不作任何改變地返回。因此請不要為 eval() 函式傳遞 String 物件來作為引數。

如果試圖覆蓋 eval 屬性或把 eval() 方法賦予另一個屬性,並通過該屬性呼叫它,則 ECMAScript 實現允許丟擲一個 EvalError 異常。
簡單點說呢:eval函式能把字串的拼接的js程式碼解析成完整的JS程式碼執行。
那麼對於上面的方法我們可以進行如下處理,直接上程式碼:

//定義接收js字串的陣列
var uploadStrArr = new Array();

儲存需要執行的js字串

/**
 * 建立檔案上傳的html
 * @param index
 * @param message
 * @param catalog
 * @returns {String}
 */
function createUploadHtml(index,message,catalog,j){
    //企業編號
    var organCode = $("#organCode").val();
    var token = "temp-parking-"+organCode+getRandomNum(parseInt(Math.random()*30));
    var uploaderNum = parseInt(Math.random()*10000);
    //定義字串
    var uploadStr="var uploader"+uploaderNum+" = new FileUpload('"+message+"',750,400,'"+catalog+"','add','jpg,png,bmp,gif');"+
     "uploader"+uploaderNum+".objectId='"+token+"'; uploader"+uploaderNum+".container='_att_files_null_"+catalog+"_"+index+"';" +
            "uploader"+uploaderNum+".show();"+
        "uploaderNumArray"+catalog+"[index-1] = uploader"+uploaderNum+";" +
        "$(\"#_att_files_null_"+catalog+"_"+index+"\").bind('DOMNodeInserted', function(e) {"+
            "var content = $(e.target).html();"+
            "if(content.indexOf(\"img\")!=-1){"+
                "$(this).attr(\"class\",\"show_image\");"+
                "$(\"#show_"+catalog+"_"+index+">a\").html();"+
                "$(\"#show_"+catalog+"_"+index+">a\").hide();"+
            "}"+
        "});"+ 
        "$(\"#_att_files_null_"+catalog+"_"+index+"\").bind('DOMNodeRemoved', function(e) {"+
            "var content = $(e.target).html();"+
            "if(content.indexOf(\"img\")!=-1){"+
                "$(\"#show_"+catalog+"_"+index+">a\").show();"+
            "}"+
        "});";

    var uploadHtml = ""+
    "<div id=\"mian_"+catalog+"_"+index+"\" class=\"upload_main_div\">"+
    "<div id=\"show_"+catalog+"_"+index+"\" class=\"fileInputContainer\">"+
    "<input id=\"attach_object_id\" name=\""+catalog+""+index+"\" value=\""+token+"\" type=\"hidden\">"+
    "<div id=\"_att_files_null_"+catalog+"_"+index+"\"></div><script src=\"/apps/attach/upload.js.jsp\"></script>"+
    "<a title=\""+message+"\" onclick=\"uploadShow("+index+","+j+")\" class=\"js-button button-icon-upload fileInput\"><span class=\"icon-upload\">&nbsp;</span><span class=\"js-button-text\">"+message+"</span></a>"+
    "</div><div class=\"upload_message_div\">上傳"+message+"<br></br></div></div>";
    //**處理核心**
    if(uploadStrArr[index-1]==undefined||uploadStrArr[index-1]==""){
        uploadStrArr[index-1] = new Array();
        uploadStrArr[index-1][j] = uploadStr;
    }else{
        uploadStrArr[index-1][j] = uploadStr;
    }
    return uploadHtml;
}

建立並定義好需要執行的js字串,注意對應。採用二維陣列接收最佳!

/**
 * 開啟上傳介面,呼叫eval函式執行
 * @param ind
 * @param j
 */
function uploadShow(ind,j){
    eval(uploadStrArr[ind-1][j]);
}

使用者點選,通過eval函式解析字串,來執行js程式碼。