深入Atlas系列 - 浅析ASP.NET Beta 2中令人疑惑的脚本引入方式

  似乎已经有不少朋友在作了ASP.NET AJAX Beta 1到Beta 2的转移之后遇到了这样的问题:如果使用了ScriptManager引入了自定义的JavaScript脚本文件后会发生JavaScript错误。例如:
< asp:ScriptManager  ID ="ScriptManager1"  runat ="server"  EnablePartialRendering ="false" >
    
< Scripts >
        
< asp:ScriptReference  Path ="MyScript.js"   />
    
Scripts >
asp:ScriptManager >

上面的代码会抛出如下的异常:“Sys.ScriptLoadFailedException: The script 'MyScript.js' could not be loaded or does not contain the Sys.Application.notifyScriptLoaded() callback.”,意思就是说我们的MyScript.js缺少了对于Sys.Application.notifyScriptLoaded函数的调用。

这表示了什么?为什么突然发生了这种状况?我们一点点地来看。


一、代码逻辑简析:

我们从页面的代码看起。上面的使用方式会产生如下的代码:
< script  src ="/ScriptResource.axd?..."  type ="text/javascript" > script >

……

< script  type ="text/javascript" >

script >

通过ScriptResource.axd文件引入的是“MicrosoftAjax.js”文件,不用多说。我们可以发现,和Beta 1的行为不同,ScriptManager并没有为添加在其中的引用添加
" );
}

protected   override   void  OnPreRenderComplete(EventArgs e)
{
    
base .OnPreRenderComplete(e);
    
this .ClientScript.RegisterStartupScript(
        
this .GetType(),  " OnPreRenderComplete "
        
" alert('OnPreRenderComplete'); " );
}

然后我们来看一下这些代码生成了什么样的客户端代码呢?如下(经过排版):
< body >
    
< form  name ="form1"  method ="post"  action ="Default.aspx"  id ="form1" >
        ……

        
< script  src ="/ScriptResource.axd?..."  type ="text/javascript" > script >

        
< script  language ="javascript" >
            alert(
" The script inside the  element. " );
        
script >
        
        
< script  language ='javascript' > alert('OnPreRender'); script >

        
< script  type ="text/javascript" >
            

         script >

        
< script  language ='javascript' > alert('OnPreRenderComplete'); script >

        
< script  type ="text/javascript" >
            

         script >
    
form >
    
    
< script  language ="javascript" >
        alert(
" The script outside the  element " )
    
script >
body >

从这里可以看出使用不同的方式,在不同的位置或者时刻注册脚本代码时,它们在页面中出现的顺序。需要注意的是,Sys.Application.initialize函数被调用后,在大多数情况下后面的代码会先于外部脚本中的代码执行。也就是说,紧跟在Sys.Application.initialize函数之后的代码无法使用外部脚本内的数据。因此,如果有任何需要在页面被加载时执行的代码,一般来说一定要写在pageLoad函数中。如下:
function  pageLoad(sender, args)
{
    
if  ( ! args.get_isPartialLoad())
    {
        
//  页面第一次被加载
    }
    
else
    {
        
//  UpdatePanel更新
    }
}

args参数是一个Sys.ApplicationLoadEventArgs对象,它的isPartailLoad属性首次出现在ASP.NET AJAX中,它就好比服务器端的IsPostBack属性一样,能够使用它很方便地判断Page Load事件的触发,是因为页面第一次加载,还是因为UpdatePanel被更新了。

你可能感兴趣的:(深入Atlas系列 - 浅析ASP.NET Beta 2中令人疑惑的脚本引入方式)