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\"> </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\"> </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程式碼。