[ExtJs] gird Store ajax 分页 过滤 查询

在处理一些大量数据时,往往用到查询,但是大量数据不适合全部查出,最好是分页查出,分页时还想有些参数过滤下,如下效果

[ExtJs] gird Store ajax 分页 过滤 查询_第1张图片

First 定义一个远端查询的store

Ext.define('项目包名.路径.store类名', {
    extend: 'Ext.data.Store',
    alias: 'store.remoteDemo',//指定store的别名
    idProperty: '列名',
    fields: [
    //fields配置参数
    ],
    remoteSort: true,//重要 指定远端排序
    remoteFilter: true,//!!重要 指定远端过滤
    pageSize:20,//指定一页行数 默认是25
     
    proxy: {
        type: 'ajax',//指定代理为ajax 通过服务端处理
        api: 'url地址'
    }
 
});

Second 前端控件引用store,并写好过滤处理

例如grid控件:在grid控件上放个可输入的文本框 用于远端查询过滤

{
    xtype:'grid',
    items:[
        {
            xtype:'toolbar',
            itemId:'tbar',
            docked: 'top',
            items:[
                {
                    xtype:'textfield',
                    name:'paramA',//自定义要查询的参数的key 
                    role: 'filter',//可以设置一个role字段来标识
                    placeholder:'查询条件1'
                },
                {
                    xtype:'textfield',
                    name:'paramB',
                    role: 'filter',
                    placeholder:'查询条件2'
                },
                {
                    xtype:'button',
                    text:'查询',
                    handler:'onSearch'//当点击查询时调用store的过滤查询
                }
            ]
        }
    ],
    plugins: {
     gridpagingtoolbar: true//使用分页插件 必备
    },
    store:{
      type:'remoteDemo'//指定第一步配置的store
    },
}

设置store查询方法处理

onSearch() {
    let grid = 通过lookup或其他查询器找到grid控件,
    store = grid.getStore(),//获取store
    filters = [];
     
    let vals;
    const bar = grid.down('#tbar'),
    fields = bar.query('field[role=filter]');//通过查询器获取用于输入过滤条件的控件
    vals = {};
    fields.forEach(field => {
        vals[field.getName()] = field.getValue();
    });
     
    for (var k in vals) {
        if (vals.hasOwnProperty(k) && !Ext.isEmpty(vals[k])) {
            filters.push({ //以键值对的形式 组成后端所需的 过滤json
                property: k,
                value: vals[k]
            });
        }
    }
     
    store.suppressNextFilter = true;
    store.clearFilter(true);//清除上次的过滤 防止数据错误
    store.setFilters(filters);//加载新的过滤条件
    store.suppressNextFilter = false;
     
    store.loadPage(1);//加载第一页
}

Third 服务端处理过滤条件,组织查询语句

后端用的C# 自己可以参照改造,反正前端传回的值都是 json格式的

定义好一个PageQueryXX方法名的方法(为何要PageQuery打头? ——容易辨识)

public StoreResult PageQuerySqlLog(StoreParams storeParams)//使用StoreResult 作为返回类型,StoreParams 类型用于接收store的各种参数
{
    string where = @"";
    List < SqlParameter > parameters = new List();
    if (storeParams.filter != null) {
        foreach(StoreFilter filter in storeParams.filter)//读取store的filter里的json信息 
        {
            if (string.IsNullOrEmpty(filter.value)) continue;
             
            if (filter.property == "paramA") {
                where += @" and T.表列名 like '%' + @参数名A + '%'";//拼接sql查询语句
                parameters.Add(new SqlParameter("@参数名A", filter.value));//为参数赋值
            }
            else if (filter.property == "paramB") {
                where += @" and T.表列名 >= @DateFr";//时间格式的demo
                SqlParameter pa = new SqlParameter("@DateFr", SqlDbType.DateTime);
                pa.Value = DateTime.Parse(filter.value);
                parameters.Add(pa);
            }
     
        }
    }
    //拼装分页查询的子查询语句
    string innerSql = string.Format(@" select 列名A,列名B from 表名 T where { 0 } ", where);//把动态拼接的where条件塞入
     
    DataTable dt = null;
    //拼接分页查询
    //!!注意: 如果想要查出满足条件的总数 在sqlSERVER中可以用 COUNT(1) OVER() as TotalCount 以在分页查询时 也统计到所有总数
    //不理解此句话就接着往下看文章
    string sql = @"
        Select S1.*, TotalCount
        From(
            select ROW_NUMBER() OVER(order by S.DocKey desc) as RowNum, COUNT(1) OVER() as TotalCount, S.*
            from
                (
                    " + innerSql + @"
                ) S
        ) S1
        where S1.RowNum >= @start And S1.RowNum <= @end
        ";
     
    SqlCommand command = new SqlCommand();
    command.CommandText = sql;
    command.Parameters.AddWithValue("@start", storeParams.start + 1);
    command.Parameters.AddWithValue("@end", storeParams.start + storeParams.limit);
    foreach(SqlParameter pa in parameters)
    {
      command.Parameters.Add(pa);
    }
    dt = ConnectionManager.ExecuteDataTable(command);
     
    StoreResult result = new StoreResult();
    result.root = dt;
    if (dt != null && dt.Rows.Count > 0)
    result.total = TypeHelper.GetIntValue(dt.Rows[0]["TotalCount"]);//将实际行数返回 不需要实际行数 就可以用下面 的Int32.MaxValue; 
    else result.total = 0;
    //若是无需知道总数 可以用 result.total = Int32.MaxValue; 
    //一般前端用的list或dataview控件 就不关心实际总数 返回result.total 值 只是用于在前端可以展示 分页
    return result;
}

自己定义了两个store的帮助类

一个是返回结果的类

namespace 命名空间
{
    [Serializable]
    public class StoreResult
    {
        public int total;
        public object root;
        public object footer;
    }
}

 另一个是store参数的类

namespace 命名空间
{
    [Serializable]
    public class StoreParams
    {
        public int page;
        public int start;
        public int limit;
        public string query; //自动完成参数
        public List group;
        public List sort;
        public List filter;
    }
    [Serializable]
    public class StoreGrouper
    {
        public string property;
        public string direction;
    }
    [Serializable]
    public class StoreSorter
    {
        public string property;
        public string direction;
    }
    [Serializable]
    public class StoreFilter
    {
        public string property;

        private string op;
        [JsonProperty("operator")]
        public string Operator
        {
            get
            {
                return op;
            }
            set
            {
                if (string.IsNullOrEmpty(value))
                {
                    if (value == "!=") op = "<>";
                    else op = value;
                }
                else
                {
                    throw WarningException.Parse("过滤器操作符{0}不合法", value);
                }
            }
        }
        public string value;
    }
}

 

其他情况:

A: 前端控件使用的是list

list使用的分页加载是不关心store的总数的,仅仅是为了出现“加载更多”字样

[ExtJs] gird Store ajax 分页 过滤 查询_第2张图片

那后端在做分页查询处理时,若是无需查出真实总数,可以用

StoreResult result = new StoreResult();
result.total = Int32.MaxValue;// 直接用个最大常量 即可

B: 前端控件使用的是Grid

如果这时还是直接返回Int32.MaxValue的话,grid的分页就会出现如下情况:

返回的不是实际总页数,这样会翻出很多空白页

这时,应该在查询分页数时,就将总条数一并查出,使用

COUNT(1) OVER () as TotalCount

一种完整的sql分页查询,连同分页行总数一并查出来了

Select S1.*,TotalCount
From (
    select ROW_NUMBER() OVER (order by S.DocKey desc) as RowNum,COUNT(1) OVER () as TotalCount, S.*
    from 
    (
        " + innerSql + @"
    ) S
) S1
where S1.RowNum >= @start And S1.RowNum <= @end

再返回前端总数值时 把查到的TotalCount 返回即可

你可能感兴趣的:(ExtJS,前端,Web前端)