Extjs 带有列表分页插件的Sencha Touch排序顺序

Extjs 带有列表分页插件的Sencha Touch排序顺序,extjs,sencha-touch,sencha-touch-2.3,Extjs,Sencha Touch,Sencha Touch 2.3,我的后端是Parse的BAAS。为了首先获取最新记录并对以前的记录进行分页,我需要按创建的时间戳降序,并使用“跳过”特定数量的记录以及每次获取的“限制”记录数。skip和limit都是+ve数字 我在ST有一个列表,需要在底部有最近的记录。当用户输入一条记录时,该记录需要追加到底部。当用户滚动到顶部时,列表需要使用分页获取以前的记录 第一个问题:为了在底部显示最近的消息,我正在按创建的时间戳的升序对ST上的列表进行排序——有没有一种方法可以在不进行排序的情况下实现这一点 第二个问题:我有一个自定

我的后端是Parse的BAAS。为了首先获取最新记录并对以前的记录进行分页,我需要按创建的时间戳降序,并使用“跳过”特定数量的记录以及每次获取的“限制”记录数。skip和limit都是+ve数字

我在ST有一个列表,需要在底部有最近的记录。当用户输入一条记录时,该记录需要追加到底部。当用户滚动到顶部时,列表需要使用分页获取以前的记录

第一个问题:为了在底部显示最近的消息,我正在按创建的时间戳的升序对ST上的列表进行排序——有没有一种方法可以在不进行排序的情况下实现这一点

第二个问题:我有一个自定义插件(列表分页插件的一个轻微变体),当滚动到顶部时,它会获取以前的记录,但即使我动态地将scrollToTop设置为false,一旦存储加载,列表会一直滚动到顶部(不带动画)。我怎样才能避免这种情况

非常感谢您的帮助!谢谢

以下是我的插件代码:

/**
 * Adds a Load More button at the bottom of the list. When the user presses this button,
 * the next page of data will be loaded into the store and appended to the List.
 *
 * By specifying `{@link #autoPaging}: true`, an 'infinite scroll' effect can be achieved,
 * i.e., the next page of content will load automatically when the user scrolls to the
 * bottom of the list.
 *
 * ## Example
 *
 *     Ext.create('Ext.dataview.List', {
 *
 *         store: Ext.create('TweetStore'),
 *
 *         plugins: [
 *             {
 *                 xclass: 'Ext.plugin.ListPaging',
 *                 autoPaging: true
 *             }
 *         ],
 *
 *         itemTpl: [
 *             '<img src="{profile_image_url}" />',
 *             '<div class="tweet">{text}</div>'
 *         ]
 *     });
 */
Ext.define('MyApp.ux.plugin.ListReversePaging', {
    extend: 'Ext.Component',
    alias: 'plugin.listreversepaging',
    config: {
        /**
         * @cfg {Boolean} autoPaging
         * True to automatically load the next page when you scroll to the bottom of the list.
         */
        autoPaging: false,
        /**
         * @cfg {String} loadMoreText The text used as the label of the Load More button.
         */
        loadMoreText: '',
        /**
         * @cfg {String} noMoreRecordsText The text used as the label of the Load More button when the Store's
         * {@link Ext.data.Store#totalCount totalCount} indicates that all of the records available on the server are
         * already loaded
         */
        noMoreRecordsText: '',
        /**
         * @private
         * @cfg {String} loadTpl The template used to render the load more text
         */
        loadTpl: [
            '<div class="{cssPrefix}loading-spinner" style="font-size: 180%; margin: 10px auto;">',
            '<span class="{cssPrefix}loading-top"></span>',
            '<span class="{cssPrefix}loading-right"></span>',
            '<span class="{cssPrefix}loading-bottom"></span>',
            '<span class="{cssPrefix}loading-left"></span>',
            '</div>',
            '<div class="{cssPrefix}list-paging-msg">{message}</div>'
        ].join(''),
        /**
         * @cfg {Object} loadMoreCmp
         * @private
         */
        loadMoreCmp: {
            xtype: 'component',
            baseCls: Ext.baseCSSPrefix + 'list-paging',
            scrollDock: 'top',
            hidden: true
        },
        /**
         * @private
         * @cfg {Boolean} loadMoreCmpAdded Indicates whether or not the load more component has been added to the List
         * yet.
         */
        loadMoreCmpAdded: false,
        /**
         * @private
         * @cfg {String} loadingCls The CSS class that is added to the {@link #loadMoreCmp} while the Store is loading
         */
        loadingCls: Ext.baseCSSPrefix + 'loading',
        /**
         * @private
         * @cfg {Ext.List} list Local reference to the List this plugin is bound to
         */
        list: null,
        /**
         * @private
         * @cfg {Ext.scroll.Scroller} scroller Local reference to the List's Scroller
         */
        scroller: null,
        /**
         * @private
         * @cfg {Boolean} loading True if the plugin has initiated a Store load that has not yet completed
         */
        loading: false
    },
    /**
     * @private
     * Sets up all of the references the plugin needs
     */
    init: function(list) {
        var scroller = list.getScrollable().
                getScroller(),
                store = list.getStore();


        this.setList(list);
        this.setScroller(scroller);
        this.bindStore(list.getStore());


        this.addLoadMoreCmp();


        // The List's Store could change at any time so make sure we are informed when that happens
        list.updateStore = Ext.Function.createInterceptor(list.updateStore, this.bindStore, this);


        if (this.getAutoPaging()) {
            scroller.on({
                scrollend: this.onScrollEnd,
                scope: this
            });
        }
    },
    /**
     * @private
     */
    bindStore: function(newStore, oldStore) {
        if (oldStore) {
            oldStore.un({
                beforeload: this.onStoreBeforeLoad,
                load: this.onStoreLoad,
                filter: this.onFilter,
                scope: this
            });
        }


        if (newStore) {
            newStore.on({
                beforeload: this.onStoreBeforeLoad,
                load: this.onStoreLoad,
                filter: this.onFilter,
                scope: this
            });
        }
    },
    /**
     * @private
     * Removes the List/DataView's loading mask because we show our own in the plugin. The logic here disables the
     * loading mask immediately if the store is autoloading. If it's not autoloading, allow the mask to show the first
     * time the Store loads, then disable it and use the plugin's loading spinner.
     * @param {Ext.data.Store} store The store that is bound to the DataView
     */
    disableDataViewMask: function() {
        var list = this.getList();
        this._listMask = list.getLoadingText();


        list.setLoadingText(null);
    },
    enableDataViewMask: function() {
        if (this._listMask) {
            var list = this.getList();
            list.setLoadingText(this._listMask);
            delete this._listMask;
        }
    },
    /**
     * @private
     */
    applyLoadTpl: function(config) {
        return (Ext.isObject(config) && config.isTemplate) ? config : new Ext.XTemplate(config);
    },
    /**
     * @private
     */
    applyLoadMoreCmp: function(config) {
        config = Ext.merge(config, {
            html: this.getLoadTpl().
                    apply({
                        cssPrefix: Ext.baseCSSPrefix,
                        message: this.getLoadMoreText()
                    }),
            scrollDock: 'bottom',
            listeners: {
                tap: {
                    fn: this.loadNextPage,
                    scope: this,
                    element: 'element'
                }
            }
        });


        return Ext.factory(config, Ext.Component, this.getLoadMoreCmp());
    },
    /**
     * @private
     * If we're using autoPaging and detect that the user has scrolled to the bottom, kick off loading of the next page
     */
    onScrollEnd: function(scroller, x, y) {

        var list = this.getList();


        if (!this.getLoading() && y <= 50) {

            this.currentScrollToTopOnRefresh = list.getScrollToTopOnRefresh();
            list.setScrollToTopOnRefresh(false);

            this.loadNextPage();
        }
    },
    /**
     * @private
     * Makes sure we add/remove the loading CSS class while the Store is loading
     */
    updateLoading: function(isLoading) {
        var loadMoreCmp = this.getLoadMoreCmp(),
                loadMoreCls = this.getLoadingCls();


        if (isLoading) {
            loadMoreCmp.addCls(loadMoreCls);
        } else {
            loadMoreCmp.removeCls(loadMoreCls);
        }
    },
    /**
     * @private
     * If the Store is just about to load but it's currently empty, we hide the load more button because this is
     * usually an outcome of setting a new Store on the List so we don't want the load more button to flash while
     * the new Store loads
     */
    onStoreBeforeLoad: function(store) {
        if (store.getCount() === 0) {
            this.getLoadMoreCmp().
                    hide();
        }
    },
    /**
     * @private
     */
    onStoreLoad: function(store) {
        var loadCmp = this.getLoadMoreCmp(),
                template = this.getLoadTpl(),
                message = this.storeFullyLoaded() ? this.getNoMoreRecordsText() : this.getLoadMoreText();


        if (store.getCount()) {
            loadCmp.show();
        }
        this.setLoading(false);


        //if we've reached the end of the data set, switch to the noMoreRecordsText
        loadCmp.setHtml(template.apply({
            cssPrefix: Ext.baseCSSPrefix,
            message: message
        }));


        if (this.currentScrollToTopOnRefresh !== undefined) {

            this.getList().
                    setScrollToTopOnRefresh(false);
            delete this.currentScrollToTopOnRefresh;
        }


        this.enableDataViewMask();
    },
    onFilter: function(store) {
        if (store.getCount() === 0) {
            this.getLoadMoreCmp().
                    hide();
        } else {
            this.getLoadMoreCmp().
                    show();
        }
    },
    /**
     * @private
     * Because the attached List's inner list element is rendered after our init function is called,
     * we need to dynamically add the loadMoreCmp later. This does this once and caches the result.
     */
    addLoadMoreCmp: function() {
        var list = this.getList(),
                cmp = this.getLoadMoreCmp();


        if (!this.getLoadMoreCmpAdded()) {
            list.add(cmp);


            /**
             * @event loadmorecmpadded  Fired when the Load More component is added to the list. Fires on the List.
             * @param {Ext.plugin.ListPaging} this The list paging plugin
             * @param {Ext.List} list The list
             */
            list.fireEvent('loadmorecmpadded', this, list);
            this.setLoadMoreCmpAdded(true);
        }


        return cmp;
    },
    /**
     * @private
     * Returns true if the Store is detected as being fully loaded, or the server did not return a total count, which
     * means we're in 'infinite' mode
     * @return {Boolean}
     */
    storeFullyLoaded: function() {
        var store = this.getList().
                getStore(),
                total = store.getTotalCount();


        return total !== null ? store.getTotalCount() <= (store.currentPage * store.getPageSize()) : false;
    },
    /**
     * @private
     */
    loadNextPage: function() {
        var me = this;
        if (!me.storeFullyLoaded()) {
            me.disableDataViewMask();
            me.setLoading(true);
            me.getList().
                    getStore().
                    nextPage({addRecords: true});
        }
    }
});
/**
*在列表底部添加“加载更多”按钮。当用户按下此按钮时,
*下一页数据将加载到存储中并附加到列表中。
*
*通过指定“{@link#autoPaging}:true”,可以实现“无限滚动”效果,
*即,当用户滚动到页面时,将自动加载下一页内容
*在名单的最后。
*
*##示例
*
*Ext.create('Ext.dataview.List'{
*
*store:Ext.create('TweetStore'),
*
*插件:[
*             {
*xclass:'Ext.plugin.ListPaging',
*自动老化:真的吗
*             }
*         ],
*
*第三方物流:[
*             '',
*“{text}”
*         ]
*     });
*/
Ext.define('MyApp.ux.plugin.ListReversePaging'{
扩展:“Ext.Component”,
别名:“plugin.listreversepaging”,
配置:{
/**
*@cfg{Boolean}自动分页
*如果为True,则在滚动到列表底部时自动加载下一页。
*/
自动老化:错误,
/**
*@cfg{String}loadMoreText用作加载更多按钮标签的文本。
*/
loadMoreText:“”,
/**
*@cfg{String}nomorecordstext存储区关闭时用作“加载更多”按钮标签的文本
*{@link Ext.data.Store#totalCount totalCount}表示服务器上可用的所有记录都是
*已加载
*/
noMoreRecordsText:“”,
/**
*@私人
*@cfg{String}loadTpl用于呈现加载更多文本的模板
*/
第三方物流:[
'',
'',
'',
'',
'',
'',
“{message}”
].加入(“”),
/**
*@cfg{Object}loadMoreCmp
*@私人
*/
loadMoreCmp:{
xtype:'组件',
baseCls:Ext.baseCSSPrefix+“列表分页”,
scrollDock:'顶部',
隐藏:真的
},
/**
*@私人
*@cfg{Boolean}loadmorecmpaded指示是否已将load more组件添加到列表中
*然而。
*/
loadMoreCmpAdded:false,
/**
*@私人
*@cfg{String}loadingCls存储加载时添加到{@link#loadMoreCmp}的CSS类
*/
loadingCls:Ext.baseCSSPrefix+“正在加载”,
/**
*@私人
*@cfg{Ext.List}List此插件绑定到的列表的本地引用
*/
列表:空,
/**
*@私人
*@cfg{Ext.scroll.Scroller}滚动器列表滚动器的本地引用
*/
滚动条:空,
/**
*@私人
*@cfg{Boolean}如果插件启动了尚未完成的存储加载,则加载为True
*/
加载:错误
},
/**
*@私人
*设置插件需要的所有引用
*/
初始化:函数(列表){
var scroller=list.getScrollable()。
getScroller(),
store=list.getStore();
这个.setList(list);
这个.setScroller(滚动条);
this.bindStore(list.getStore());
this.addLoadMoreCmp();
//该列表的存储可能随时更改,因此请确保在发生这种情况时通知我们
list.updateStore=Ext.Function.createInterceptor(list.updateStore,this.bindStore,this);
if(this.getAutoPaging()){
卷轴({
scrollend:this.onScrollEnd,
范围:本
});
}
},
/**
*@私人
*/
bindStore:功能(新闻商店、旧商店){
如果(旧商店){
旧商店({
beforeload:this.onStoreBeforeLoad,
load:this.onStoreLoad,
过滤器:this.onFilter,
范围:本
});
}
if(新闻商店){
纽约新闻商店({
beforeload:this.onStoreBeforeLoad,
load:this.onStoreLoad,
过滤器:this.onFilter,
范围:本
});
}
},
/**
*@私人
*删除列表/数据视图的加载掩码,因为我们在插件中显示了自己的掩码
*如果存储正在自动加载,则立即加载掩码。如果不是自动加载,则允许掩码显示第一个掩码
*对存储加载计时,然后禁用它并使用插件的加载微调器。
*@param{Ext.data.Store}存储绑定到DataView的存储
*/
disableDataViewMask:函数(){
var list=this.getList();
这是._listMask=list.getLoadingText();
列表
var totalCount = myStore.getTotalCount();  //lets say there are 10 elements
var recordMsg  = {title : "User message", content, "Hello"}; //create new model /record  

myStore.insert(totalCount, recordMsg); // so since there are 10 elements indexes 0 -9 are already taken, lets use index 10 and put it at the end