今天对项目进行测试的时候发现一个很有趣的问题,跟大家分享下。首先说下做的是个什么样的功能,废话不多说上图:
这是一个简单的表单数据
从第二章图片可以看出来,这个实体是可以在一个页面添加多个的。
对于一个页面添加多条数据,以及对数据的处理,后台代码等功能都比较简单,这里我就直接跳过。下面说说我遇到的问题:
我在做图片上传的时候,每一个图片的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代码。