现在的位置: 首页 > easyui > Layout > panel > 正文
浅析panel组件href方式脚本的执行顺序
2012年05月15日 panel ⁄ 共 2065字 评论数 16 ⁄ 被围观 17,552 views+
文章目录
[隐藏]

概要分析

粗略地分析panel的源码我们知道,panel的href方式获取数据使用的是jQuery的ajax方法,ajax获取返回纯文本,该文本作为变量传给success回调,也就是说,在success内部交由panel组件进一步处理,我们来看看代码片段:

  1. $.ajax({   
  2.     url: _18e.options.href,   
  3.     cache: false,   
  4.     success: function(data){   
  5.         _190.html(_18e.options.extractor.call(_18d, data));   
  6.         if ($.parser) {   
  7.             $.parser.parse(_190);   
  8.         }   
  9.         _18e.options.onLoad.apply(_18d, arguments);   
  10.         _18e.isLoaded = true;   
  11.     }   
  12. });  

通过上面代码可以看出:获取远程数据data作为参数送给success回调,在success内部,我们看到panel使用自身的extractor函数对data文本进一步过滤,这个过滤过程不重要,我们可以忽略。过滤后的数据直接使用jQuery的html()追加到当前DOM,然后easyui使用paser对追加的html片段进行渲染。

分析到这个地方,我想关键点我们就都已经找到了,明确以下两点最重要:

data内部包含的javascript片段的执行顺序取决于jQuery的html函数的处理机制
data内部包含的javascript片段一定先于easyui的parser执行

html函数机制:

第一步.将DOM中的script标签剥离出来,从而形成两部分内容,一部分是不包含script标签的文本,假设为A;另一部分是若干个script片段,假设为B。

第二步.清空当前标签,用A追加到当前标签。

第三步.追加B到当前页面,而且对于B,有两种情况:

  • script标签使用src方式连接到其它js文件的情况:jQuery使用ajax函数获取src里面的javascript代码,并且ajax设置为同步,从而能保证按照引入顺序执行;
  • 直接写在script标签里面的javascript代码:jQuery使用window.execScript或者window[ "eval" ]执行javascript代码.

结论归纳:

分析到这里基本就清晰了,所以,最后href目标页面中的javascript脚本的注意事项有以下几点:

script标签必须放在body内

script标签一定要放在body标签内部,放在body标签外面的所有script标签都会被忽略,或者直接省略掉html,head,body这几个标签页可以。

script的位置无关性

script标签包含的脚本不管是放在DOM最前面,还是中间,还是后面,从执行效果上讲,都好比按顺序地放在了DOM的最后面。因为是先追加不带script标签的DOM,后处理分离出来的script。这也是放在某个DIV前面的脚本可以通过这个DIV的ID属性访问到该DIV的原因,这一点跟正常页面的加载顺序是有区别的。

 失去作用的document.ready

比如目标页面的内容如下:

  1. <script type="text/javascript">   
  2.     $(function(){   
  3.         alert("这里先执行");   
  4.     });   
  5.     alert("这里后执行");   
  6. </script>  

要是在普通页面内,document.ready里面的脚本肯定是在后面执行的,当其作为panel的href目标页面的时候ready是没有任何效果的,因为这时候页面早就加载完成的,ajax当然不在ready检测的范围内。

不要操作不存在的组件实例

目标页面里面的javascript代码不应该存在直接利用easyui组件实例对象的操作,比如$("#panelId").panel('setTitle','shit'),除非你在次之前调用了$("#panelId").panel({...});来生成panel组件的对象实例。

后知后觉的easyui parser

如果data里面包含easyui支持的组件class,那么在$.parser.parse(_190)代码执行完后将会完成对组件的解析,所以最安全的方式是在onLoad回调中操作easyui组件的实力对象。

不要重复构造easyui组件

还需要注意的是,不要重复构造easyui组件了,如果在data内部通过脚本构造了某easyui组件,然后$.parser.parse检索到该组件样式,又构造一次,这纯粹是浪费,而且可能造成两次加载。

还有哪些组件类似?

layout,according等扩展自panel的上层组件使用href的时候,脚本执行顺序的规则是跟panel组件一致的。

目前有 16 条留言 其中:访客:10 条, 博主:6 条

  1. 下午茶 : 2012年12月20日16:32:01  -49楼 @回复 回复

    晕死… 我就用Chrome看了半天源文件,发现herf回来的页面只有body里面的东西,里面的按钮调用的JS全都是显示未定义。估计就是过滤掉了,看了你的文章后,果然如此…


    • 管理员
      世纪之光 : 2012年12月20日16:57:42  地下1层 @回复 回复

      奔泪吆,终于来了一个有头像的到我这里留言了……

      • 下午茶 : 2012年12月20日17:08:01  地下2层 @回复 回复

        哈哈,好悲催啊。我还在研究中… 尝试了好几种方式,直接ajax把内容取回来然后放到dialog的content中去,好像还是有点问题,script就是无论如何都要被干掉一样… 疯了…


        • 管理员
          世纪之光 : 2012年12月20日17:14:42  地下3层 @回复 回复

          把ajax的目标请求页面的所有javascript都放在body内部就可以了呀,easyui的规则一直是这样的。

          • 下午茶 : 2012年12月20日17:21:38  地下4层 @回复 回复

            这个我知道的… 可是不想这样啊… 这要一来格局变动太大了…


            • 管理员
              世纪之光 : 2012年12月20日17:44:35  地下5层 @回复 回复

              那你可以试着研究一下panel组件的extractor属性,它起到过滤掉的作用。

              • 下午茶 : 2012年12月20日19:08:06  地下6层 @回复 回复

                那个属性之前我试过了,给了个参数data,但是没有执行,不知道为什么。
                //
                href:xxxx,
                extractor:function(data){
                //xxxx
                }
                试了没反应…


  2. 管理员
    世纪之光 : 2012年12月20日19:24:46  -48楼 @回复 回复

    @下午茶 没反应是什么意思啊,执行不进去?我试了是可以的啊 直接
    extractor:function(data){
    alert(1);//可以打印出来
    }
    如果要包含整个html的话,你的正则估计就复杂了,一个页面中不能包含两个head和title元素吧?

    • 下午茶 : 2012年12月21日11:03:45  地下1层 @回复 回复

      是没反应,我用浏览器Debug了,从头到尾根本没有进来,没有执行过这个方法。
      你用的是哪个版本的jQuery和EasyUI? 我用的是jq1.7.2,easyui1.3。
      $(‘#show-task-dialog’).show().dialog({
      href : url,//这个是生成好的一个地址变量
      title:title,
      maximized : true,
      closable : true,
      modal : true,
      cache:false,
      draggable:false,
      loadingMessage : ‘数据加载中…’,
      extractor:function(data){
      //此处照抄过来测试的
      console.log(‘data’,data);
      var pattern = /]*>((.|[\n\r])*)/im;
      var matches = pattern.exec(data);
      console.log(‘matches’,matches);
      if (matches){
      return matches[1]; // only extract body content
      } else {
      return data;
      }
      }
      });

      代码用的没问题吧? 方便的话帖帖你的。


      • 管理员
        世纪之光 : 2012年12月21日15:56:18  地下2层 @回复 回复

        我之前定义panel组件的extractor是有效的。而定义dialog的extractor,我试了下,确实无效,看了下dialog的代码,初始化组建的时候并没有使用自身定义的extractor覆盖panel组件定义的extractor。所以你想改的话,就这样改 $.fn.panel.defaults.extractor = function(data){alert(data);}。

        • 下午茶 : 2013年01月09日12:02:34  地下3层 @回复 回复

          哈哈,多谢多谢。之前没有看到你的回复,我用了iframe方式实现了功能。不过你说的也不错,我得培养看源码的习惯了~ 😀

  3. Gaion : 2013年12月16日15:26:42  -47楼 @回复 回复

    今天看到这篇文章,但是对于“$(function(){})无法正常使用”,有一点疑问,因为目前试验的过程发现都有效啊……包括说明中的实例

    $(function(){
    alert(“这里先执行”);
    });
    alert(“这里后执行”);


    • 管理员
      世纪之光 : 2013年12月16日18:49:16  地下1层 @回复 回复

      “失去作用”并非是“无法使用”的意思。
      $(function(){
      alert(“1”);
      });
      alert(“2”);
      以上代码,在普通页面内的正常情况,应该是先弹出”2″再弹出”1″,但是如果是panel的href的话,则是先弹出”1″后弹出”2″。我想表述的是这个意思。

      • Gaion : 2013年12月30日09:45:42  地下2层 @回复 回复

        了解……多谢了哈。看了这篇文章受益匪浅

  4. liang : 2014年04月22日17:13:30  -46楼 @回复 回复

    多谢 终于知道为啥加载不上了

  5. 落叶走天涯 : 2014年10月28日10:46:44  -45楼 @回复 回复

    非常清晰的解释,几乎明白了easyui加载href的原理,能否讲解下css文件是如何加载的

给我留言

留言无头像?


×