日期:2014-05-16  浏览次数:20447 次

ExtJs实现刷新Grid单个单元格

产生问题背景:

ExtJS3.2版本

页面上存在定时刷新表格的功能,而且表格中每行又有详情,当每次刷新每行时,即执行了Record的Set方法,详情都会关闭。刚开始觉得很奇怪。因为我一直觉得,我刷新一行中的一个字段的话,那应该是只更新这个字段的DOM就行了。

?

后台查看了一下源代码原来,每个Record数据变化时,其实都是重新生成一条新行的DOM。在源代码的执行步骤是,先新插入一行,再把旧数据的行DOM删除换。

?

由于详情是属于行的,所以,每次执行Record的Set后,行重新生成,那么详情肯定会删除掉。

?

为了解决详情不关闭这个问题,我们想方法为Record自定义一个Replace方法出来。

?

它的功能是:使用Record的Replace方法,可以实现单个字段的更新。

?

看起来很空间的一句话,可是为了实现这个功能,重写了ExtJs很多的“类”才实现了。下面是为了实现这个功能代码,

?

还带了实现了一个功能,使用ExtJs提供的冒泡提示加到表格的字段值中。

Ext.onReady(function(){
	//要使用ExtJS提供的冒泡提示,必须加上下面这句
	Ext.QuickTips.init();
	Ext.override(Ext.grid.ColumnModel,{
		//根据列定义时的给出的ID,得到该列的渲染方法,其实是为了更新单个单元格时,显示与定义一致
		getRendererById:function(id){
			return this.getRenderer(this.getIndexById(id));
		}
	});
	//步骤4:
	Ext.data.Record.REPLACE = 'repalce';//定义一个记录的替换命令,目前没有什么作用
	Ext.override(Ext.data.Record,{
			//替换单个字段的值的方法
			replace : function(name, value){
				var encode = Ext.isPrimitive(value) ? String : Ext.encode;
				if(encode(this.data[name]) == encode(value)) {
					return;
				}        
				this.dirty = true;
				if(!this.modified){
					this.modified = {};
				}
				if(this.modified[name] === undefined){
					this.modified[name] = this.data[name];
				}
				this.data[name] = value;//模型更新
				this.afterReplace(name,value);//通过Store通知gridview视图更新
			},
			//通过Store通知gridview视图更新方法
			afterReplace:function(name,value){
				 if (this.store != undefined && typeof this.store.afterReplace == "function") {
					this.store.afterReplace(this,name,value);
				}
			}
    });
	//步骤5:
	Ext.override(Ext.data.Store,{
				//新定义的通知gridview视图更新的方法
			    afterReplace : function(record,name,value){
					if(this.modified.indexOf(record) == -1){
						this.modified.push(record);
					}
					//通知视图更新
					this.fireEvent('repalce',record,name,value, Ext.data.Record.REPLACE);
				}
		}
	);
    var myData = [
        ['3m Co',71.72,0.02,0.03,'9/1 12:00am'],
        ['Alcoa Inc',29.01,0.42,1.47,'9/1 12:00am'],
        ['Altria Group Inc',83.81,0.28,0.34,'9/1 12:00am']
    ];

    // example of custom renderer function
    function change(val){
        if(val > 0){
            return '<span qtip="'+val+'" style="color:green;">' + val + '</span>';
        }else if(val < 0){
            return '<span qtip="'+val+'" style="color:red;">' + val + '</span>';
        }
        return val;
    }
	//使用ExtJS提供的冒泡提示
	function titleQtip(val){
		return '<span qtip="'+val+'">' + val + '</span>';
	}
    // example of custom renderer function
    function pctChange(val){
        if(val > 0){
            return '<span style="color:green;">' + val + '%</span>';
        }else if(val < 0){
            return '<span style="color:red;">' + val + '%</span>';
        }
        return val;
    }

    // create the data store
    var store = new Ext.data.Store({
        proxy: new Ext.ux.data.PagingMemoryProxy(myData),
        remoteSort:true,
        sortInfo: {field:'price', direction:'ASC'},
        reader: new Ext.data.ArrayReader({
            fields: [
               {name: 'company'},
               {name: 'price', type: 'float'},
               {name: 'change', type: 'float'},
               {name: 'pctChange', type: 'float'},
               {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
            ]
        })
    });
	Ext.override(Ext.grid.GridView,{
			////步骤7:真正实现GridView更新单个单元格的方法
			onReplace:function(record,name,value){
				 var ds = this.ds, index;
				if(Ext.isNumber(record)){
					index = record;
					record = ds.getAt(index);
					if(!record){
						return;
					}
				}else{
					index = ds.indexOf(record);
					if(index < 0){
						return;
					}
				}
				//实现单个字段的更新
				document.getElementById(index+name).innerHTML = this.cm.getRendererById(name).call(this,value);
		},
		//步骤6:
	initData : function(ds, cm){
        if(t