现在的位置: 首页 > easyui > Layout > tabs > 正文
浅谈 easyui tabs 的href和content属性
2012年02月17日 tabs ⁄ 共 3211字 评论数 48 ⁄ 被围观 84,739 views+
文章目录
[隐藏]

众所周知,jQuery Easyui 的tabs插件有两种方式加载某个tab(标签页)上的内容:“href远程请求”和“content本地内容”,本文就两种方式的优缺点进行简单分析和思考。

两者特点:

href方式加载数据的特点:
  • 被加载的页面只有body元素内部的内容才会被加载,也就是jQuery的ajax请求的只是html片段。
  • 加载远程url时有遮罩效果,也就是“等待中……”效果,用户体验较好。
  • 当加载的页面布局较为复杂,或者有较多的js脚本需要运行的时候,编码往往就需要谨慎了,容易出问题,后面会详细谈。
content方式加载数据的特点:
  • 比较灵活,你可以在脚本里面拼写html代码,然后赋值给tab的content属性,不过这种写法会使得代码易读性变差。
  • 可以把iframe赋给content,把一个iframe嵌入也就没有什么不能完成的了。
  • 使用iframe会造成客户端js重复加载,浪费资源,比如说你主页面要引用easyui的库,你的iframe也要引用,浪费就产生了。

简单总结:

根据上面的分析,使用content的方式较为简洁,而且可以引入iframe来搞定一切,缺点也很明显,系统较为复杂的话,将带来极大地资源浪费,只适合较为简单的页面系统;

而href方式则对编码能力要求的稍微高一些,因为html的片段,稍微不注意就会处理不好,不过熟练的话,个人觉得href方式是不二之选。

href常见问题:

1.href只加载目标URL的html片段

这个特性是由jQuery封装的ajax请求处理机制所决定的,所以目标URL页面里不需要有html,head,body等标签,即使有这些元素,也会被忽略,所以放在head标签里面的任何脚本也不会被引入或者执行。

2.短暂的页面混乱:

href链接的页面比较复杂的时候,easyui对其渲染往往需要一个较长的过程,这时候,加载进来的html片段毫无布局可以,过一会自动会好,这时候easyui已经完成对它的渲染。如何避免这个混乱的过程呢,还得靠easyui的一个基础插件——解析器(Parser)。

Parser有个onComplete事件,这个事件就是指easyui对页面完成渲染时触发,这样思路就很清晰了:用一个div遮罩住让被加载进来的html片段,在onComplete事件中,让这个div淡出,这时候渲染好的html片段就能美人出浴了,同时还整了个等待中的效果,一举两得。这样要做两件事:

第一是在要加载的html片段中放一个遮罩用的div:

  1. <div id="loading" style="position: absolute; z-index: 1000; top: 0px; left: 0px; width: 100%; height: 100%; background: #DDDDDB; text-align: center; padding-top: 20%;"></div>

第二是在被加载的html片段尾部处理相关事件:

  1. function show(){
  2.     $("#loading").fadeOut("normal"function(){
  3.         $(this).remove();
  4.     });
  5. }
  6. var delayTime;
  7. $.parser.onComplete = function(){
  8.     if(delayTime)
  9.         clearTimeout(delayTime);
  10.     delayTime = setTimeout(show,500);
  11. }

需要注意的是,如果多个tab页面都使用了onComplete事件,当前定义的会覆盖之前定义的。其实每次easyui渲染完成均会调用onComplete事件,所以每打开一个包含easyui控件的tab页,onComplete事件就会被调用。

3.html片段的easyui组件相关脚本莫名地报错:

其实这个现象是跟第一个现象的原因一样的,easyui完成对html片段渲染需要一定的时间,页面越复杂,耗时越长,这时候难以避免html存在的脚本存在对easyui某些插件的调用,比如datagrid等,这个时候就会报错,解决方案同上,将这些脚本放到onComplete事件里处理,也就保证了渲染完成前,不会被执行。

4.放在window里面表单验证的提示信息会乱串:

这个现象应该是插件自身的bug,对位置的计算没有考虑到这些特殊的事情,解决方式可以投机取巧,在打开window后,让表单不符合验证的input获得焦点就可以了。

5.两次或者多次加载远程数据问题:

官方已经说明在1.2.5的版本中已经修正了这个Bug,但是还是有不少人反应会出现两次加载远程数据的现象,甚至在1.2.6版本中也会遇到,如果您确实遇到这种情况了,则可能有以下情况造成的:

5.1,自己的代码不严谨造成的,这是比较低级的错误,如果遇到请按照以下两个步骤检查原因:

  • 远程数据返回的数据中是否包含class="easyui-tabs"或者class="easyui-datagrid"这样的样式了, 如果有的话,easyui在获取html片段后会自动渲染,这时候已经对远程数据源做了一次请求;
  • 您是否又用javascript去$('#tabsId').tabs({...});或者$('#tabsId').datagrid({...});去绑定事件或者设置属性,其实等于又一次渲染了该应控件,会再次请求远程数据。

为什么会这样,看看源码便知道了:

  1. $.fn.tabs = function(options, param){
  2.     if (typeof options == 'string') {
  3.         //这个地方的分支很清楚,只有当options为字符串的时候,才是直接调用控件本身提供的方法。
  4.         return $.fn.tabs.methods[options](this, param);
  5.     }
  6.     //如果options不是字符串,直接构造控件,进行渲染。
  7.     options = options || {};
  8.     return this.each(function(){
  9.         var state = $.data(this, 'tabs');
  10.         var opts;
  11.         if (state) {
  12.             opts = $.extend(state.options, options);
  13.             state.options = opts;
  14.         }
  15.         else {
  16.             $.data(this, 'tabs', {
  17.                 options: $.extend({}, $.fn.tabs.defaults, $.fn.tabs.parseOptions(this), options),
  18.                 tabs: wrapTabs(this),
  19.                 selectHis: []
  20.             });
  21.         }
  22.         buildButton(this);
  23.         setProperties(this);
  24.         setSize(this);
  25.         initSelectTab(this);
  26.     });
  27. };

所以请大家写代码的时候还是要注意点,有现成的控件方法就用该方法,直接传入对象的话,所有控件都会重新构造的,tabs多次加载的问题大多数就是这么发生的。

5.2,事件冒泡引起的二次加载也是有可能的,详细情况请参照:
http://www.easyui.info/archives/501.html

目前有 48 条留言 其中:访客:26 条, 博主:20 条 引用: 2

  1. christy : 2012年02月29日21:45:51  -49楼 @回复 回复

    你好,我使用的是easyui 1.2.5,更新日志里说明已经解决了添加tab时href发送两次请求的BUG。但我在使用href方式加载页面的时候总会加载3-4次,而且会报datagrid的一些错误,我按照你说的使用parser,仍然不起作用。PS:我的href链接是个动态action链接。


  2. 管理员
    世纪之光 : 2012年03月01日08:40:27  -48楼 @回复 回复

    @christy
    你好:重复加载跟解析器(parser)的使用没什么关系,光从描述来看不好定位问题,你把你是如何添加tab页的代码发给我看看吧,还有目标的动态页代码也发过来,发到邮箱:caoguanghuicgh@163.com

  3. christy : 2012年03月04日13:05:21  -47楼 @回复 回复

    @世纪之光
    这个问题解决了,使用href方式添加的页面里,有一个datagrid,我使用的是用js方式构造datagrid,同时又在这个table上加了一个”easyui-datagird”的class:,这样会莫名的加载两次,去掉这个class就可以了….真是个郁闷的错误。呵呵,还是谢谢博主。


  4. 管理员
    世纪之光 : 2012年03月04日13:32:56  -46楼 @回复 回复

    @christy
    看不到你具体的代码,不过我觉得你既用class为”easyui-datagrid”的方式去渲染,又去用js方式渲染,$.parser.onComplete事件至少被促发两次,但是我觉得只要你table的href属性不加的话,是不会做多次加载的,你可以按照以下方式试试:table上还是加”easyui-datagrid”样式,但是不要申明href属性,在js构造的时候设置href,这样的话,应该不会多次加载。
    一个问题解决了,如果不找出原因的话,那就会浪费解决问题所付出的时间和代价,你觉得我分析的是原因的话,建议你去试一试。

  5. 瑞晨 : 2012年07月28日23:04:27  -45楼 @回复 回复

    请问下。如何使用href的方式并且加载所有的代码。body以外的也加载,如何做到。


  6. 管理员
    世纪之光 : 2012年07月29日14:30:02  -44楼 @回复 回复

    @瑞晨
    你能先说说你为什么会有这个想法,你是基于何种需求要这样做的呢?

  7. How to make will : 2012年09月04日06:53:44  -43楼 @回复 回复

    Do you mind if I quote a couple of your posts as long as I provide credit and sources back to your weblog? My website is in the exact same area of interest as yours and my visitors would really benefit from some of the information you provide here. Please let me know if this ok with you. Appreciate it!

  8. Liny : 2012年09月12日11:17:56  -42楼 @回复 回复

    如何通过点击tab将grid添加到对应的tab里面去? 3Q

    • Liny : 2012年09月12日11:18:55  地下1层 @回复 回复

      咦?标签被过滤掉了?


      • 管理员
        世纪之光 : 2012年09月13日16:55:18  地下2层 @回复 回复

        html标签确实是会被过滤的,要不然岂不是影响正常的页面布局……

  9. 乐楽樂 : 2012年09月21日23:36:48  -41楼 @回复 回复

    您是否又用javascript去$(‘#tabsId’).tabs({…});或者$(‘#tabsId’).datagrid({…});去绑定事件或者设置属性,其实等于又一次渲染了该应控件,会再次请求远程数据。

    但是我确实需要$(‘#tabsId’).tabs({…});来设置某个属性.这样怎么写啊?这样写了以后就必然导致href加载两次的.太郁闷了


    • 管理员
      世纪之光 : 2012年09月22日12:26:02  地下1层 @回复 回复

      @乐楽樂 所以说改变属性的方法并不是调用构造函数重新构造控件,而是要调用控件提供的相关接口方法去设置属性,比如设置标题的方法等等,利用options方法也可以重新设置一些属性,常常被用在改变控件的href属性上,然后重新加载。

  10. wing2002li : 2012年10月22日12:27:58  -40楼 @回复 回复

    我用iframe 加载,A页面有一个datagrid ,B页面一个datagrid,A和B同时增加,结果只显示B页面的datagrid,不显示A页面的datagrid,如何处理。


    • 管理员
      世纪之光 : 2012年10月22日14:01:48  地下1层 @回复 回复

      @wing2002li 
      你好,这样的问题我没办法一下子说出答案,请提供一个可能重现问题的包含脚本的html文档,我可以试着帮你分析问题原因。

      • wing2002li : 2012年10月22日14:50:29  地下2层 @回复 回复

        @世纪之光  你有QQ吗?我说下有三个页面,
        index页面,主要功能,主页面,加两个tab,这两个tab分别用iframe引用页面datagrid.html和datagrid2.html,显示后,datagrid2.html中的数据显示,datagrid.html的数据不显示,datagrid.html和datagrid2.html两个页面来自于官方的demo。目录jquery-easyui-1.3\demo文件夹下。
        index页面的代码:

        关于测试

        var mainTabs;
        $(function () {
        mainTabs = $(“#tt”).tabs();
        tabMainAdd();
        });
        function tabMainAdd() {
        mainTabs.tabs(‘add’, {
        id: ‘tab_’ + “1”,
        title: “a1”,
        closable: false,
        content: makeIframe(‘datagrid.html’)
        });
        mainTabs.tabs(‘add’, {
        id: ‘tab_’ + “1”,
        title: “b1″,
        closable: false,
        content: makeIframe(‘datagrid2.html’)
        });
        }
        makeIframe = function (src) {
        if (src && src.length > 0)
        return ”;
        else
        return “src is empty.”;
        }


        • 管理员
          世纪之光 : 2012年10月22日16:44:47  地下3层 @回复 回复

          @wing2002li 加QQ群126894273,一起讨论。

          • kskepler : 2013年08月08日13:56:52  地下4层 @回复 回复

            最后有啥结论么?
            我现在也在做一个类似的功能,页面打开,显示3个tab,每个tab的div里放一个iframe,去加载其他的datagrid的jsp,总是第一个tab显示和功能一切正常,第2个,第3个的iframe加载不出页面…..

      • wing2002li : 2012年10月22日16:05:26  地下2层 @回复 回复

        @世纪之光  貌似没办法全贴出。

  11. 小明 : 2013年04月11日18:45:20  -39楼 @回复 回复

    我有一个tabs在一个layout中,这个tabs中包含一个jsp页面,此页面的内容是一个表单.当我提交这个表单的时候,整个layout页面都被刷新了…整个窗口变成了那个jsp页面…

    我怎么做到提交这个表单的时候,只刷新表单所在的页面,即tabs里的那个jsp页面,而不是整个窗口一起刷新,结果整个窗口变成了那个jsp页面.


    • 管理员
      世纪之光 : 2013年04月11日20:09:01  地下1层 @回复 回复

      最简单的方式使用ajax提交,不要使用form自带的submit的方式提交。对于使用submit原生方式提交表单的方式是否也能实现ajax效果,我还真没怎么关注过。

  12. 小明 : 2013年08月22日15:00:21  -38楼 @回复 回复

    我有一个tabs,里面显示服务器返回的页面,我称它为a.html.
    但是当用户登录超时的时候,服务器会返回让用户重现登录的页面,我称它为b.html.
    现在我希望当返回a.html的时候,页面正常在这个tabs里显示.
    而当返回b.html的时候,我希望整个tabs所在的当前页面跳转成b.html.
    而不是在tabs里显示b.html.

    我目前碰到的问题就是b.html在tabs中显示了.怎么做才能让tabs所在的当前页面整个跳转成b.html呢,请赐教~


    • 管理员
      世纪之光 : 2013年08月22日20:35:21  地下1层 @回复 回复

      这个问题其实跟前台框架没有什么关系,你用的iframe的话,当然只能在iframe内部跳转。如果要实现整个页面跳转的话,iframe方式下,有两种方案:
      1、可以在onAdd事件中延时执行一段检查iframe内部页面的代码(要求b.html有明显区别于正常页面的特征),如果确认iframe内部是b.html页面,则在onAdd事件中重新定向当前整个页面为b.html.
      2、可以在b.html页面上做工作,b.html接受一点的参数,用于区别b.html页面是单独请求,还是被放在iframe里面请求的,如果是放在iframe里面被请求的,则通过parnet对象将父页面刷新为b.html

  13. songsong : 2013年12月02日10:32:13  -37楼 @回复 回复

    你好,我想问一下,我是动态请求的action ,action 后面传递的参数会出现乱码怎么解决?页面上,服务器上我都已经设置了编码方式utf-8.


    • 管理员
      世纪之光 : 2013年12月03日09:17:43  地下1层 @回复 回复

      乱码问题比较复杂吧,建议你好好查查资料,首先试试javascript的encodeURI函数。

  14. 天赐Easy : 2014年04月15日17:24:58  -36楼 @回复 回复

    我每次吧 content设置时

    tabs标题的高度会越来越高


    • 管理员
      世纪之光 : 2014年04月19日12:35:50  地下1层 @回复 回复

      你的描述 我不是很理解。

      • 张天赐Easy : 2014年04月19日15:48:57  地下2层 @回复 回复

        这个我已经解决了, 好像是我们的美工调过样式造成的这种现象,我在tabs的属性里面设置tabheight为一个固定值就可以, 但是具体原因还不知道为什么, 这个结论是我通过跟踪easyui内部js得出的,他在我没有设置这个属性的时候,内部循环会获取这个值,这个值是auto, 这样他在添加,更新,删除tabs选项卡的时候,每次会把现在已有的tabs选项卡的高度+1,这样就会到这选项卡那一行的高度越来越高


        • 管理员
          世纪之光 : 2014年04月19日18:22:58  地下3层 @回复 回复

          所以有些问题你这么简单的描述 别说我不是很理解,即便是理解了,也很难就知道原因。

  15. hailiang : 2014年05月07日15:06:46  -35楼 @回复 回复

    你好 !
    关于easyui tabs控件的exists和select方法能否根据tab id来判断是否存在和选中tab呢?
    目前官网上只给title 或index两个参数,这样我菜单中相同title不同url的就只能显示一个了 😛


    • 管理员
      世纪之光 : 2014年05月08日09:27:39  地下1层 @回复 回复

      从实现上讲,肯定是可以的,不过tabs组件自身的设计没有支持根据ID去获取某个panel,你可以自己扩展一个existsById 和 selectById方法,id这个属性并不是每个panel都会有的,你用add方法增加的时候可以指定ID,但是用DOM方式初始化的话标签不一定就有ID了。

  16. uuuuuu : 2014年05月30日14:56:21  -34楼 @回复 回复

    我利用add在tabs新添加一个panel,每个新panel会去加载同一个或href,但是新添加的页面不会出现href界面,而是刷新了旧的panel,这个怎么解决呢?


    • 管理员
      世纪之光 : 2014年05月31日00:38:13  地下1层 @回复 回复

      麻烦把demo发给我,否则没法分析你的问题。

      • uuuuuu : 2014年05月31日08:27:42  地下2层 @回复 回复

        西部面板的代码:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        
        $(document).ready(function () {
            var tt = document.getElementById("tt");
            $.getJSON("http://localhost:8080/WSNServer/tempsensor", function (data) {
                var obj = data.sensorIP;
                for (var i = 0; i < obj.length; i++) {
                    tt.innerHTML = tt.innerHTML +
                        "节点:"
                        + obj[i] + "";
                }
            });
        });
        //添加panel的代码:
        function addTabs(data) {
            var ip = '' + data.textContent;
        //console.info(ip);
            var t = $('#layout_center_tabs');
            var options = {
                title: ip,
                closable: true,
                href: 'layout/center.jsp?ip=' + encodeURI(encodeURI(ip))
            };
            if (t.tabs('exists', options.title)) {
                t.tabs('select', options.title);
            } else {
                t.tabs('add', options);
            }
        }
  17. bruce : 2014年08月22日14:16:51  -33楼 @回复 回复

    请问我通过iframe加载的tab怎样改为用href加载呢?
    下面是我加载tab的代码,麻烦您看看,或者提供一个用href加载的左右布局的示例,谢谢
    function addTab(subtitle,url,icon){
    if(!$(‘#tabs’).tabs(‘exists’,subtitle)){
    $(‘#tabs’).tabs(‘add’,{
    title:subtitle,
    content:createFrame(url),
    closable:true,
    icon:icon
    });
    }else{
    $(‘#tabs’).tabs(‘select’,subtitle);
    $(‘#mm-tabupdate’).click();
    }
    tabClose();
    }

    function createFrame(url)
    {
    var s = ”;
    return s;
    }

  18. yayn : 2014年08月27日10:28:22  -32楼 @回复 回复

    我用的是tabs的href为什么datagrid的验证不起作用呢?我在那个母版已经引入了所需要的js,datagrid就是验证不起作用?


    • 管理员
      世纪之光 : 2014年08月27日11:05:28  地下1层 @回复 回复

      不是很清楚你所谓问的问题,如果是validatebox问题的话,请看看脚本有无报错,相关规则有无扩展。

  19. 复活 : 2014年09月02日10:51:13  -31楼 @回复 回复

    请教:easyui tabs的z-index的值是多少,怎么修改呢?谢谢


    • 管理员
      世纪之光 : 2014年09月02日20:04:14  地下1层 @回复 回复

      你好,tabs组件里面没有设置任何z-index值。

  20. wo : 2015年02月13日11:33:03  -30楼 @回复 回复

    老大,到底用iframe好还是href好

    如果用href的话,是不是整个系统中,所有的组件都必须保证其唯一性

    如果是的话,请问怎么保证,自己编码的时候制定规则吗

    譬如:datagrid01,datagird02这样?


    • 管理员
      世纪之光 : 2015年02月13日16:31:01  地下1层 @回复 回复

      个人觉得没有必要规定一个系统必须全部使用某一种方式,最好是根据需要,可以灵活设置是href还是iframe。

      href方式下,唯一性确实是个很重要的问题,通常的做法就是你说的思路,对编码定制规则。有兴趣完善easyUI框架的话,也可以试着将某些规则写到easyui的源码里。

  21. lv_tk : 2015年04月17日11:03:06  -29楼 @回复 回复

    请教作者一个问题,我生成调用addtab页面的时候,用href=xxx。php,想向这个php传递数据请问应该怎么做呢,谢谢,有点急,望解答,回复我的邮箱谢谢


    • 管理员
      世纪之光 : 2015年04月18日15:54:41  地下1层 @回复 回复

      你用url方式传参就是了,例如:href = home.php?name=John

  22. 威尔 : 2015年12月11日11:44:15  -28楼 @回复 回复

    这个特性是由jQuery封装的ajax请求处理机制所决定的,所以目标URL页面里不需要有html,head,body等标签,即使有这些元素,也会被忽略,所以放在head标签里面的任何脚本也不会被引入或者执行。

    我想知道这个jquery是怎么实现的

  23. hundry : 2016年09月01日17:08:16  -27楼 @回复 回复

    你好,我遇到了个特殊问题:
    我采用href加载,在火狐浏览器下正常,但在其它浏览器下都一直处于loading状态,源代码如下,请帮忙看下什么原因,谢谢:
    $(‘#tabEmlGnlStt’).tabs({
    onSelect: function(title, index) {
    var tab = $(‘#tabEmlGnlStt’).tabs(‘getSelected’);
    if(index == ‘1’) {
    $(‘#tabEmlGnlStt’).tabs(‘update’, {
    tab: tab,
    options: {
    href: ‘blklst-setting.html’, //the new content URL
    }
    });
    } else if(index == ‘2’) {
    $(‘#tabEmlGnlStt’).tabs(‘update’, {
    tab: tab,
    options: {
    href: ‘frdusr-setting.html’, // the new content URL
    }
    });
    } else if(index == ‘3’) {
    $(‘#tabEmlGnlStt’).tabs(‘update’, {
    tab: tab,
    options: {
    href: ’emlads-setting.html’, // the new content URL
    }
    });
    } else {
    return;
    }
    }
    });


    • 管理员
      世纪之光 : 2016年09月03日00:02:54  地下1层 @回复 回复

      大多数浏览器对本地资源的访问是受安全策略限制的,你要将你的代码跑在服务器上才行。

给我留言

留言无头像?


×