给元素注册事件时,事件函数中不能使用全局变量

      最近在做项目的过程中,遇到这样的需求(为了便于说明,我对源需求进行了简化):需要通过js创建新的file元素,并要对新建的元素注册事件和添加属性。(注册的事件是用来在客户端验证上传的文件的大小和格式的)。

 

      以下的代码并不是我项目中的代码,项目中的代码远比这个要复杂的多,而且摘下来的话,大家看的也费力。所以我就本着通俗易懂的原则,截取了一部分,并加工了一下。以便让大家更容易读懂!代码如下:

 

<script type="text/javascript>

    var  globalOne = 0;    // 全局变量

    var  globalTwo = 0;    // 全局变量

   

    /*在此方法中,给新建元素注册的事件函数要用到全局变量的当前*/

    function createElement(parentElement){

          globalOne++;

          globalTwo++;

 

          var tempOne = globalOne;   // 保存全局变量globalOne的当前值

          var tempTwo = globalTwo;   // 保存全局变量globalTwo的当前值

 

           parentElement.appendChild(document.createTextNode("图片:"));
          var textFiled3_pic = document.createElement("<input name=/"surveyOptPicfile_" + globalOne+ "_" +   (globalTwo+ 1) + "/" >");
          textFiled3_pic.setAttribute("type", "file");
          textFiled3_pic.className = "input200";
          textFiled3_pic.setAttribute("id", "surveyOptPicfile_" + globalOne+ "_" + (globalTwo + 1));

 

          // 注册onchange事件
          textFiled3_pic.attachEvent("onchange", function(){ var id = "surveyOptPicfile_" + globalOne+ "_" + (globalTwo+ 1); changeSrc(document.getElementById(id), id);});      // 此处不正确,不能用全局变量(本意是取得全局变量当时的值)

 

          textFiled3_pic.attachEvent("onchange", function(){ var id = "surveyOptPicfile_" + tempOne + "_" + (tempTwo + 1); changeSrc(document.getElementById(id), id);});      // 此处正确(本意是取得全局变量当时的值)


          parentElement.appendChild(textFiled3_pic);    // 把创建的元素追加到父元素中

    }

 

    function  changeSrc(obj, id){

     

        // 在此做一些验证

    }

 

</script>

 

      在上面的注册onchange事件代码中,为什么红色标明的部分不正确,而绿色标明部分正确呢!

      原因是在js中给新创建的元素注册事件时,注册的事件函数并不会在注册的时候就会被元素加载的,而是在元素的注册事件被触发的时候才加载,即执行事件定义的方法;但元素设置的属性,却会在元素定义之后立即被加载。大家可以通过在ie中用调试工具(或火狐的firebug)查看创建的元素的代码;代码中并不会显示事件。

      所以,如果大家以红色的代码注册事件。当触发onchange事件时,注册函数中定义的变量id的值并不是当时注册的时候的全局变量的值;而是全局变量的当前值。要想让id的值重现全局变量重现当时注册时候的值,就应该使用绿色标明部分的代码。

 

      说了这么多,也不知道我说明白了没有。下面我就给一简单的完整的例子——这样也算是对我上面说的一种解释吧。下面的代码兼容IE和火狐,其中蓝色标明部分的代码,请根据自己的浏览器注释掉不需要的部分。简单介绍下面的这段代码的作用:该段代码可以创建多个上传文件的file元素,在每个创建的file元素都注册一个onchange事件,用于验证上传的图片格式是否是.jpg或.gif或.png格式的。

 

<html>
<head>
<script type="text/javascript">
    var  globalOne = 0;    // 全局变量
    var  globalTwo = 0;    // 全局变量

    /*在此方法中,给新建元素注册的事件函数要用到全局变量的当前*/
    function createFileElement(parentElement){
          globalOne++;
          globalTwo++;

          var tempOne = globalOne;   // 保存全局变量globalOne的当前值
          var tempTwo = globalTwo;   // 保存全局变量globalTwo的当前值

   parentElement.appendChild(document.createTextNode("新增上传图片组件" + globalOne + ":"));
   /** IE创建新元素,并注册事件
          var textFiled3_pic = document.createElement("<input name=/"surveyOptPicfile_" + globalOne + "_" +  (globalTwo+ 1) + "/" >");
          textFiled3_pic.className = "input200";
          textFiled3_pic.setAttribute("id", "surveyOptPicfile_" + globalOne+ "_" + (globalTwo + 1));
          // 注册onchange事件
   textFiled3_pic.attachEvent("onchange", function(){ var id = "surveyOptPicfile_" + tempOne + "_" + (tempTwo + 1); changeSrc(document.getElementById(id), id);});
   */

 

   /** FF创建新元素,并注册事件*/
   var textFiled3_pic = document.createElement("input");
          textFiled3_pic.setAttribute("name", "surveyOptPicfile_" + globalOne+ "_" + (globalTwo+ 1));
          textFiled3_pic.setAttribute("type", "file");
          textFiled3_pic.setAttribute("class", "input200");
          textFiled3_pic.setAttribute("id", "surveyOptPicfile_" + globalOne+ "_" + (globalTwo+ 1));
          textFiled3_pic.addEventListener("change", function(){var id = "surveyOptPicfile_" + tempOne + "_" + (tempTwo + 1); changeSrc(document.getElementById(id), id);}, false);

         

   parentElement.appendChild(textFiled3_pic);    // 把创建的元素追加到父元素中
 
    }

 

// 验证文件格式(当然大家也可在这个函数中做其他一些操作)
function changeSrc(fileObj, fileElementId)
{
  var fileName = fileObj.value;
  if(!fileName.match(//.jpg|/.gif|/.png/ig)){
   alert("您上传的图片格式不正确!");
 return false;
  }
  return true;
}
</script>
</head>
<body>
<form name="form1" id="form1">
请选择图片:<input type="file" name="surveyOptPicfile_0_0" id="surveyOptPicfile_0_0" onchange="changeSrc(this, 'surveyOptPicfile_0_0')">
<input type="button" value="增加上传组件" onclick="createFileElement(document.form1);">

</form>
</body>
</html>

 

大家可以直接把上面的代码拷到本地执行!(如果在注册onchange事件的时候不是textFiled3_pic.addEventListener("change", function(){var id = "surveyOptPicfile_" + tempOne + "_" + (tempTwo + 1); changeSrc(document.getElementById(id), id);}, false);        而是使用全局变量textFiled3_pic.addEventListener("change", function(){var id = "surveyOptPicfile_" + globalOne+ "_" + (globalTwo+ 1); changeSrc(document.getElementById(id), id);}, false);   则用新创建的file组件上传图片,不能正确的验证上传的图片格式,即使你上传的格式正确,也会提示你格式错了!大家可以试试!

另:在注册事件中使用关键字this也将不起作用,而是会把它当做普通的字符串!

 

 

 

 

 

 

 

posted @ 2009-08-25 13:03  hibernate3例子  阅读(278)  评论(0编辑  收藏  举报