读GI源码、学JS编程——Javascript动态加载技术。

在大型RIA中,动态加载技术十分重要,毕竟几百K甚至M级别的脚本让用户等待加载完了再浏览是不可能。大多数成熟的framework都有动态加载技术的实现,就是说先加载一个最基础功能,然后利用动态加载技术慢慢把所有的脚本加进来,或者说需要某个功能的时候再加载某个模块所  需要的javascript的文件。

好了不说那么多P话了,尽快进入正题来看看GI是怎么实现的动态加载技术。其实GI的load做的很复杂,因为他涉及到了进度条阿等等很多乱七八糟的东西,我们就不分析那么多东西了,来看看他最基础的东西是如何实现的吧。GI中的动态加载有两种,一种是用的是XMLHttpRequest来请求脚本内容,另一种则是加入一个 <script>标签的方式来动态加入脚本以达到动态加载的功能。网上也许还有其它得方法,但其它得方法也都是根据这两种演变来的,还是以这两种为基础得。我们来看看它是如何实现的。

首先是第一种

       /* * @private @jsxobf-clobber  */
      ClassLoader_prototype.loadJSFileSync 
=   function (strURI) {
        
var  req  =   new  jsx3.net.Request();
        req.open(
" GET " , strURI,  false );
        req.send();
            
        
if  (req.getStatus()  ==  jsx3.net.Request.STATUS_OK) {
          
var  script  =  req.getResponseText();
          jsx3.eval(script);
          
return   true ;
        }

        
return   false ;
      };

呵呵,XMLHttpRequest的GET请求就可以吧js文件拿下来,然后用eval执行所有的脚本,这样就达到了加载脚本的功能了。方法也很简单,也就不用多介绍什么了吧。不过我记着有人说过js必须要UTG-8格式存的,但测试了一下,不用好像也可以。

我们看在package。Js文件里面有个有意思的方法

   /* *
   * Ensures that one or more classes is available before this method returns. Any class that fails to load will
   * throw an error. Only classes that can be found by the system class loader may be loaded in this manner.
   *
   * @param strClass {String} the fully-qualified names of the classes to load.
   * @since 3.2
   
*/
  jsx3.require 
=   function (strClass) {
    
for  ( var  i  =   0 ; i  <  arguments.length; i ++ ) {
      
var  className  =  arguments[i];
      className 
=  jsx3._REQUIRE_MAP[className]  ||  className;
      
if  (jsx3.Class.forName(className)  ==   null )
        jsx3.CLASS_LOADER.loadClass(className);
    }
  };

需要说明的是jsx3.ClASS_LOADER.loadClass()方法中其实就是调用了loadJSFileSync()方法,这个方法就是在调用类之前如果该类没有被加载将会在被load一次做到需要什么才用什么,不会把所有Javascipt都加载进来。

然后我们再来看第二种方法,添加标签的方式来load脚本

       /* * @private @jsxobf-clobber  */
      ClassLoader_prototype.loadScript 
=   function (strSrc, strId) {
        
//  instance a new DOM element
         var  element  =  document.createElement( " script " );
        element.src 
=  strSrc;
        element.type 
=  'text / javascript';
        element.id 
=  strId;
        element.language 
=  'javascript';
        
        
//  set up onload handler
         var  me  =   this ;
        
if  ( this .IE) {
          element.onreadystatechange 
=   function () { 
            
var  state  =   this .readyState;
            
if  (state  ==   " loaded "   ||  state  ==   " interactive "   ||  state  ==   " complete " ) {
              
this .onreadystatechange  =   null ;
              me._loaded[strSrc] 
=   true ;
              me._publish({subject:
" load " , type: " script " , src:strSrc});
            }
          };
        } 
else   if  ( this .MOZ  ||   this .KON) {
          element.onload 
=   function () { 
            element.onload 
=   null ;
            me._loaded[strSrc] 
=   true ;
            me._publish({subject:
" load " , type: " script " , src:strSrc}); 
          };
        }
        
        element.jsxid 
=  strSrc;
        
        
//  bind the element to the browser DOM to begin loading the resource
        document.getElementsByTagName( " head " )[ 0 ].appendChild(element);
      };


呵呵,相信大家都能看懂吧,就是在head标签中加入了script标签,src当然就是重点了,而如何判断脚本加载结束,也明确的告诉我们,在IE下用onreadystatechange,在Firefox下用onload。呵呵,好像很简单吧。

到这里,我突然想到一个问题,script标签好像功能很强大啊,竟然可以用来读服务器上的Javascript文件,跟XMLHttpRequest有同样的功能啊,看来这个东西可以被我们来利用一下了,做点手脚也许会有不同的效果哦,来看。

首先我们写一个Handlers用来模拟一个Javascript文件,然后用这个handler来生成返回的内容,

       < httpHandlers >
        
< add  verb ="*"  type ="JsTest.JsHandler"  path ="demo2.js" />
      
</ httpHandlers >

     public   class  JsHandler:IHttpHandler,IRequiresSessionState
    {
        
public   void  ProcessRequest(HttpContext context)
        {
            
string  action  =  context.Request[ " action " ].ToString();
            context.Response.Write(
" alert(\ " hello world   "  + action +  " \ " ); " );
        }
}

这个Handler中我只是返回了一段alert,呵呵,下面用script来加载他吧,刚才看到的一样,只是script中src我们做了点手脚,嘿嘿指向的是demo2.js?action=city22,哈哈看到了吧,就是个GET访问方式啊!

window.onload = function ()
{
    
var  script = document.createElement( " script " );
    script.type
= 'text / javascript';
    script.language
= 'javascript';
    script.src
= " demo2.js?action=city22 " ;
    document.getElementsByTagName(
" head " )[ 0 ].appendChild(script);
}

测试成功,哈,看来还真是能模拟一个XMLHttpRequest了。

不过有人肯定该问了,这个有什么用XMLHttpRequest已经很好用了啊,干嘛在来个这东西。我感觉这东西在一定的领域还是能发挥作用的。XMLHttpRequest不能垮站访问,这是个问题,也就是说你在www.a.net/index.html上写了一段XMLHttpRequest不能调用www.b.net上的任何东西,即使改动document.domian 也不可以,唉多可惜。当然了Iframe给我们解决了这个问题,但是script标签又给了我们新的选择,我们完全可以模拟open(),send(),等这些方法,返回的脚本中使用变量作为返回内容来模拟responseText。看来跨站问题又有了新的解决思路了。以后script标签值得我们去深入研究一下咯。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值