Ext2.0代码跟踪:GridPanel只有一行记录时,字段修改也触发select事件

背景:

界面有两个GridPanel,分别为发票列表、费用列表。一个必要对应多个费用进行核销。

应用上,选择一个发票记录时,自动加载对应的同一业务下的费用,并计算出总费用金额。将费用总金额回写到选择的发票核销金额字段。

当发票有多行记录时,一切正常。当发票只有一条时,发生死循环。

 

调试:初步调试发现,如果只有一条发票时,费用加载完自己又清除掉,然后再加载。

        查看Ext源代码,发现为Ext2.0的一个bug。在Ext2.2以后都已经解决。

 

过程:

1,回写发票的核销金额时,调用了Record的set方法。

 

set : function(name, value){
        if(String(this.data[name]) == String(value)){
            return;
        }
        this.dirty = true;
        if(!this.modified){
            this.modified = {};
        }
        if(typeof this.modified[name] == 'undefined'){
            this.modified[name] = this.data[name];
        }
        this.data[name] = value;
        if(!this.editing && this.store){
            this.store.afterEdit(this);
        }
    }

 

  2,Store的afterEdit方法,触发update事件

 

 // private
    afterEdit : function(record){
        if(this.modified.indexOf(record) == -1){
            this.modified.push(record);
        }
        this.fireEvent("update", this, record, Ext.data.Record.EDIT);//触发事件,查看相关的监听者,猜测在GridView或GridPanel
    },

 

  3,GridView监听了store的update事件,进而触发了onUpdate方法。

而onUpdate直接调用了refreshRow方法。

这里,可以看到当Record改变时,GridView采取的方法是先insertRowsonRemove。最后才触发rowupdated事件。跟踪过rowupdated事件的监听者,未发现异常。

因为是只有一行记录才出现问题,所以需要对数字的判断敏感一些。

当只有一条Record时,在insertRows方法中,实际只是刷新了一下。并没有真正的删除。

接下去就是看refresh方法做什么?

 

// private
    initData : function(ds, cm){
        if(this.ds){
            //省略……
        }
        if(ds){
            ds.on("load", this.onLoad, this);
            ds.on("datachanged", this.onDataChange, this);
            ds.on("add", this.onAdd, this);
            ds.on("remove", this.onRemove, this);
            ds.on("update", this.onUpdate, this);
            ds.on("clear", this.onClear, this);
        }
        this.ds = ds;
       //省略....
    },
// private
    onUpdate : function(ds, record){
        this.refreshRow(record);
    },
// private
    refreshRow : function(record){
        var ds = this.ds, index;
        if(typeof record == 'number'){
            index = record;
            record = ds.getAt(index);
        }else{
            index = ds.indexOf(record);
        }
        var cls = [];
        this.insertRows(ds, index, index, true);
        this.getRow(index).rowIndex = index;
        this.onRemove(ds, record, index+1, true);
        this.fireEvent("rowupdated", this, index, record);
    },
insertRows : function(dm, firstRow, lastRow, isUpdate){
        if(firstRow === 0 && lastRow == dm.getCount()-1){
            this.refresh();
        }else{
            if(!isUpdate){
                this.fireEvent("beforerowsinserted", this, firstRow, lastRow);
            }
            var html = this.renderRows(firstRow, lastRow);
            var before = this.getRow(firstRow);
            if(before){
                Ext.DomHelper.insertHtml('beforeBegin', before, html);
            }else{
                Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
            }
            if(!isUpdate){
                this.fireEvent("rowsinserted", this, firstRow, lastRow);
                this.processRows(firstRow);
            }
        }
    }
 

 

4,GridView的refresh触发了refresh事件,进而触发Ext.grid.RowSelectionModel的onRefresh函数。

直接便抛出了选择修改事件。

 

 onRefresh : function(){
        var ds = this.grid.store, index;
        var s = this.getSelections();
        this.clearSelections(true);
        for(var i = 0, len = s.length; i < len; i++){
            var r = s[i];
            if((index = ds.indexOfId(r.id)) != -1){
                this.selectRow(index, true);
            }
        }
        if(s.length != this.selections.getCount()){
            this.fireEvent("selectionchange", this);
        }
    }
 

 

 

综合上代码跟踪。第3步中的GridView的insertRows方法调用了refresh()是导致问题所在。则重写此方法解决此问题。

 

/**
 * 解决Grid只有一条数据时,对该记录调用set方法时,会造成刷新/选择事件
 *20101125.1 By  Simon
 */
Ext.grid.GridView.prototype.insertRows = function(dm, firstRow, lastRow, isUpdate) {
	if (!isUpdate && firstRow === 0 && lastRow >= dm.getCount() - 1) {//加入判断是否只是update
		this.refresh();
	} else {
		if (!isUpdate) {
			this.fireEvent("beforerowsinserted", this, firstRow, lastRow);
		}
		var html = this.renderRows(firstRow, lastRow);
		var before = this.getRow(firstRow);
		if (before) {
			Ext.DomHelper.insertHtml('beforeBegin', before, html);
		} else {
			Ext.DomHelper.insertHtml('beforeEnd', this.mainBody.dom, html);
		}
		if (!isUpdate) {
			this.fireEvent("rowsinserted", this, firstRow, lastRow);
			this.processRows(firstRow);
		}
	}
	this.syncFocusEl(firstRow);
};
 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值