现在的位置: 首页 > easyui > Grid > datagrid > 正文
阻止datagrid填充已经获取到的远程数据
2013年01月01日 datagrid ⁄ 共 2806字 评论数 9 ⁄ 被围观 13,737 views+

时光流逝,弹指挥间,不经意的一年又如路上一个动人的靓影悄然消失在视线里。我们往往都是先问自己,我们收获了什么,然后才想到我们付出了什么,很少有人先问自己这一年付出了什么,然后再去看所得。话不多说了,祝靠着搜索引擎来到此地的同仁们,在2013年能够大付出,然后大收入。

当datagrid设置了url属性,表格就会通过ajax向设置的url请求数据,然后把请求的数据放到已经渲染好的表格容器中,整个过程我们可以这样简单地表示:

datagrid组件url方式加载数据流程图

上图的几点说明:

  • onBeforeLoad事件发生在ajax请求之前的,这个事件函数如果返回false的话,将直接结束,不会请求数据。
  • onLoadError事件是当ajax请求出现故障时触发,开发者可以在此事件中自定义提示信息等。
  • onBeforeRender事件是view属性的,该事件发生在把ajax请求到的数据填充到表格内容中之前。
  • 红色部分的rend数据行,就是把ajax请求到的数据填充到表格内容里,这个操作是调用view的render方法实现的。
  • onAfterRender事件也是view对象的事件,该事件在数据填充到表格之后触发。
  • view对象是全局性的,就是说当前页面,所有datagrid对象公用这个view,这是由闭包与面向对象特性决定的,我们来看datagrid的鱼源码:
    /**
     * 自动运行的匿名函数
     * @param {Object} _1b6
     * @param {Object} _1b7
     * @param {Object} _1b8
     */
    (function($){ 
    	//view为匿名函数的内部变量,其指向一个对象。
        var view = {
            render: function(_1b6, _1b7, _1b8){
                //...
            },
            renderFooter: function(_1bf, _1c0, _1c1){
                //...
            },
            renderRow: function(_1c4, _1c5, _1c6, _1c7, _1c8){
                //...
            },
            refreshRow: function(_1ce, _1cf){
                //...
            },
            updateRow: function(_1d0, _1d1, row){
                //...
            },
            insertRow: function(_1d7, _1d8, row){
                //...
            },
            deleteRow: function(_1e2, _1e3){
                //...
            },
            onBeforeRender: function(_1e8, rows){
    			//user defined
            },
            onAfterRender: function(_1e9){
                //...
            }
        };
    	//将匿名函数的内部变量赋给$.fn.datagrid.defaults全局对象
    	//这样就构成了闭包,匿名函数内的view变量在匿名函数的运行结束后继续存在于内存中。
        $.fn.datagrid.defaults = $.extend({}, $.fn.panel.defaults, {
            //...
            view: view
    		//...
        });
    })(jQuery);
    

    所以,如果我们更改某个表格的view.onBeforeRender属性的话,其实就是对全局对象的更改,除非我们直接覆盖某个表格的view指向,这样就不会影响其它表格的view了:

    $('#tt').datagrid('options').view.onBeforeRender = function(jq,rows){};//这样就改变了全局变量,对别的grid也会造成影响
    $('#tt').datagrid('options').view = {onBeforeRender :function(jq,rows){},...};//这样只改变了tt表格的view,对别的grid不会造成影响
    
  • onLoadSuccess事件发生最后,这时候数据已经填充到表格,木已成舟,已无回天之力,除非重新砍木头。
  • 在数据填充到表格后,datagrid还有一件事要做,那就是刷新分页工具栏的总记录数值。

我们可以看到,整个过程中,我们唯一有机会阻止ajax加载到的数据填充到表格的地方就是onBeforeRender事件,只要在这个事件里面,我们将数据设置为空,不过也就没有内容可以填充了;

我们可以直接覆写某个表格的view,不过代码量太大,所以更改全局的view对象的onBeforeRender事件更为简洁,因view对象是公用的,你更改的话,那么在当前页面,所有表格的view就都跟着改了,所以在view的onBeforeRender最好是通过入参的id标识用以标识哪些表格需要阻止特定数据填充到内容区,所以,我们在页面文档装载完做以下定义:

$(function() {
			$.fn.datagrid.defaults.view.onBeforeRender = function(ele, rows) {
				if (ele.id == 'test') {// 只处理id为test的表格
					if (rows.length && rows[0].key == -1) {// 这地方我们假设回台返回的数据key为-1的话,则代表此次请求的数据均为错误提示信息,不与展示。
						$(ele).data('datagrid').data = {
							total : 0,
							rows : []
						};
						alert(rows[0].error);// 用弹出窗口方式通知用户获取数据出错。
					}
				}
			}
		});

到这里,我们只剩下一个问题了,那就是分页栏还是显示有一条或多条数据,而根据代码的流程图我看可以看出分页栏的刷新是放在最后的,是不是就没辙了呢?别担心,我们有setTimeout这个法宝,在onLoadSuccess事件里面我们延时刷新一下分页栏就行了:

onLoadSuccess:function(data){
				setTimeout(function(){
					var page = $('#test').datagrid("getPager");
					page.pagination('refresh',{total:0});
				},100);	
}

是不是有的童鞋要喊了:“既然分页条能延时刷新,那表格的内容也可以延时清空啊。”,不错表格内容是可以通过延时的方式来清空,但是这个过程用户的眼睛一直盯着表格内容,其展示和被清空的过程被用户看得一清二楚。而分页栏是死角,没人会在意,这就是区别。

到这里,我们也就算是完美地完成我们想要的效果了,善于思考的同学肯定会问,为什么要用这么别扭的方式,后台报错就直接不要返回什么数据,都放在onLoadError事件里提示不就得了。

事实上大多人也将异常放在onLoadError中处理的,只有少数情况才会对后台返回的数据有特殊要求,此文更重要的目的是讲述datagrid组件url方式加载和填充数据的过程。

目前有 9 条留言 其中:访客:5 条, 博主:4 条

  1. 小明 : 2013年02月20日00:02:16  -49楼 @回复 回复

    我在页面上用js的方式创建一个datagrid,其中url属性为一个struts的action,这个action产生的数据加载到datagrid.

    我现在希望在第一次打开页面时,不要加载datagrid,也就是说不要访问这个action,让datagrid保持空的状态.然后用户点查询的时候我会调用datagrid的load方法,这时候再访问这个action.有什么好点的方法么.

    前端或后端的解决方案都行,不过我前端功力较差,想了半天,办法是有,但是感觉不怎么优雅.还希望您能指点一二.


    • 管理员
      世纪之光 : 2013年02月20日00:54:42  地下1层 @回复 回复

      这个问题不是很容易解决吗,你在页面上用js创建datagrid的时候不要设置url属性,然后在用户点击查询的时候你先使用datagrid的options方法设置url属性,然后再调用load方法加载数据,这样不就解决了吗?

      1. $(‘#grid’).datagrid(‘options’).url = ‘你的action地址’;   
      2. $(‘#grid’).datagrid(‘load’);  
      • 小明 : 2013年02月20日10:05:39  地下2层 @回复 回复

        搞定,谢谢!
        我一直以为在创建datagrid的时候url是一个必须设的属性,所以一直陷在这个思维里了.
        以后碰到前端的问题还来找你哈,当然,我会把问题描述清楚的~到时候还望您不吝赐教~


        • 管理员
          世纪之光 : 2013年02月20日10:13:52  地下3层 @回复 回复

          不客气,我懂的也不多,到我这里也别抱太多希望哈 😈

  2. 小明 : 2013年02月21日10:02:14  -48楼 @回复 回复

    我又来了,再提几个脑残的问题,实在不好意思,搞不定.
    Pagination组件上能自己定义一些按钮(buttons属性),这些按钮是不是linkbutton呀,如果是,我怎么得到这些linkbutton的引用,因为我想对这些按钮做一些操作,比如让它们变的不可用什么的.


    • 管理员
      世纪之光 : 2013年02月21日10:19:33  地下1层 @回复 回复

      你可以看一下组件间的依赖关系图,我的下面这篇文章里有:
      jQuery Easyui组件依赖关系图
      Pagination依赖linkbutton组件说明Pagination组件里面的按钮肯定是linkbutton。
      至于如何得到这些linkbutton,可能比较麻烦,你可以使用jquery的选择器,按照按钮索引问题按钮名称检索即可得到。

      • 小明 : 2013年02月21日12:37:21  地下2层 @回复 回复

        好的,我试试,谢谢~

  3. ty : 2013年11月29日21:44:19  -47楼 @回复 回复

    有个问题,为什么不能用 var tree = $(‘#id’).tree({}); tree.tree({
    绑定事件}); 为什么会加载两次 👿 ❓


    • 管理员
      世纪之光 : 2013年12月01日12:41:48  地下1层 @回复 回复

      你这个写法已经是构造两次组件实例了,传入对象便会重新构造组件实例,这是EasyUI的规则。

给我留言

留言无头像?


×