`
Relucent
  • 浏览: 207001 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

ExtJS 3.1.0 中Ext.data.Store关于baseParams的BUG修正

    博客分类:
  • JS
阅读更多

 ExtJs 中,我们使用GirdPanel的时候往往需要给后台传递查询条件。

一般是通过修改Store的baseParams。

 

var store = GirdPanel.getStore();
store.baseParams = { 查询条件 }
store.reload(); //刷新表格

 

 

这个方法在ExtJs 2.x 和 ExtJS 3.0.0 中都使用。

 

但是当使用ExtJS 3.1.0的时候,问题就出现了。

我们会发现无论如何修改baseParams,查询条件依然还是第一次修改baseParams时候的条件。

 

所以我们无法通过修改baseParams 来满足修改查询条件的目的。

 

 

于是我们观察ExtJS 3.1.0源码发现

reload : function(options){
    this.load(Ext.applyIf(options||{}, this.lastOptions));
}

 

这里我们要说一下lastOptions的作用。

lastOptions用于保留最后一次的查询配置信息。

 

 

我们再去跟踪其他部分的代码。

 

这个是load的时候的代码。

我们可以看到首先使用storeOptions 方法保存了最后一次的查询条件。然后在调用execute执行查询。

 

    load : function(options) {
        options = options || {};
        this.storeOptions(options);
        if(this.sortInfo && this.remoteSort){
            var pn = this.paramNames;
            options.params = options.params || {};
            options.params[pn.sort] = this.sortInfo.field;
            options.params[pn.dir] = this.sortInfo.direction;
        }
        try {
            return this.execute('read', null, options); // <-- null represents rs.  No rs for load actions.
        } catch(e) {
            this.handleException(e);
            return false;
        }
    },

 

 

    storeOptions : function(o){
        o = Ext.apply({}, o);
        delete o.callback;
        delete o.scope;
        this.lastOptions = o;
    },

 

   execute : function(action, rs, options, /* private */ batch) {
        if (!Ext.data.Api.isAction(action)) {
            throw new Ext.data.Api.Error('execute', action);
        }
        options = Ext.applyIf(options||{}, {
            params: {}
        });
        if(batch !== undefined){
            this.addToBatch(batch);
        }
        var doRequest = true;
        if (action === 'read') {
            Ext.applyIf(options.params, this.baseParams);
            doRequest = this.fireEvent('beforeload', this, options);
        }
        else {
            if (this.writer.listful === true && this.restful !== true) {
                rs = (Ext.isArray(rs)) ? rs : [rs];
            }
            else if (Ext.isArray(rs) && rs.length == 1) {
                rs = rs.shift();
            }
            if ((doRequest = this.fireEvent('beforewrite', this, action, rs, options)) !== false) {
                this.writer.apply(options.params, this.baseParams, action, rs);
            }
        }
        if (doRequest !== false) {            if (this.writer && this.proxy.url && !this.proxy.restful && !Ext.data.Api.hasUniqueUrl(this.proxy, action)) {
                options.params.xaction = action;               }
                 this.proxy.request(Ext.data.Api.actions[action], rs, options.params, this.reader, this.createCallback(action, rs, batch), this, options);
        }
        return doRequest;
    },

 

 

我们重点关注

storeOptions 方法中的 o = Ext.apply({}, o);

execute 的  Ext.applyIf(options.params, this.baseParams);

 

 

 

他的目的是这样的。

首先

[storeOptions ]

克隆一个新的 Options ,并保存到lastOptions中。

lastOptions使用新的Options的目的是原有Options发生变化lastOptions不变。

 

[execute ]

然后将baseParams的内容添加到Options.params中,并使用Options.params作为参数进行查询。

 

 

逻辑上没有错误

是将baseParams内容添加到原有的Options.params中。

新的lastOptions(Options2)内容不变。(因为是克隆的)

 

但是实际上Options.params发生变化的而同时。lastOptions中的params也发生了变化。

 

原因在storeOptions 方法上。

 o = Ext.apply({}, o);
做的只是一个浅层拷贝。拷贝之后

lastOptions.params 和 Options.params  其实是一个对象。

所以当Options.params发生变化lastOptions.params也发生变化。

(不知道是Jack Slocum故意这么设计的还是没有考虑周全,不过这造成了版本的不兼容

 

 

原因找到了,修改起来也就容易了。我们只需要重构storeOptions 方法,将其params也拷贝一次就可以了。

 

Ext.override(Ext.data.Store, {
  storeOptions : function(o) {
    o = Ext.apply({}, o);
    if(o.params)
      o.params = Ext.apply({}, o.params);
    }
    delete o.callback;
    delete o.scope;
    this.lastOptions = o;
  }
});

  

分享到:
评论
1 楼 zhangdaiping 2010-07-21  
<p>load( Object options ) : Boolean</p>
<p>Loads the Record cache from the configured proxy using the configured reader.</p>
<p> </p>
<p><strong>Notes</strong>:</p>
<p style="padding-left: 30px;"> </p>
<ul>
<li>Important: loading is asynchronous! This call will return before the new data has been loaded. To perform any post-processing where information from the load call is required, specify the callback function to be called, or use a a 'load' event handler.</li>
<li>If using remote paging, the first load call must specify the start and limit properties in the options.params property to establish the initial position within the dataset, and the number of Records to cache on each read from the Proxy.</li>
<li>If using remote sorting, the configured sortInfo will be automatically included with the posted parameters according to the specified paramNames.</li>
</ul>
<p> </p>
<p><strong>Parameters</strong>:</p>
<p> </p>
<p><strong>options</strong> : Object</p>
<p style="padding-left: 30px;">An object containing properties which control loading options:</p>
<p> </p>
<p style="padding-left: 30px;">params :Object</p>
<p style="padding-left: 60px;">An object containing properties to pass as HTTP parameters to a remote data source. Note: params will override any baseParams of the same name.</p>
<p style="padding-left: 60px;">Parameters are encoded as standard HTTP parameters using Ext.urlEncode.</p>
<p style="padding-left: 30px;"> </p>
<p style="padding-left: 30px;">callback : Function</p>
<p style="padding-left: 60px;">A function to be called after the Records have been loaded. The callback is called after the load event is fired, and is passed the following arguments:</p>
<p style="padding-left: 90px;">r : Ext.data.Record[] An Array of Records loaded.</p>
<p style="padding-left: 90px;">options : Options object from the load call.</p>
<p style="padding-left: 90px;">success : Boolean success indicator.</p>
<p style="padding-left: 30px;"> </p>
<p style="padding-left: 30px;">scope : Object</p>
<p style="padding-left: 60px;">Scope with which to call the callback (defaults to the Store object)</p>
<p style="padding-left: 30px;"> </p>
<p style="padding-left: 30px;">add : Boolean</p>
<p style="padding-left: 60px;">Indicator to append loaded records rather than replace the current cache. Note: see note for loadData</p>
<p> </p>

相关推荐

Global site tag (gtag.js) - Google Analytics