zoukankan      html  css  js  c++  java
  • select2,利用ajax高效查询大数据列表(可搜索、可分页)

    本地实战结果

    二、导入css和js到网站上

    1.使用CDN,节省自己网站的流量

    2.下载文件到本地,可以做一些个性的定制(比如说修改提示语)

    git下载地址

    1
    2
    3
    4
    5
    <!-- select2 -->
    <link rel="stylesheet" type="text/css" href="${ctx}/common/select2/css/select2.css" rel="external nofollow" />
    <script type="text/javascript" src="${ctx}/common/select2/js/select2.full.js"></script>
    <!-- 中文国际化还需要进行参数设置 -->
    <script type="text/javascript" src="${ctx}/common/select2/js/i18n/zh-CN.js"></script>

    三、真刀真枪的干起来

    第一步、定制页面个性化元素

    1
    2
    3
    <select name="parentid" class="js-data-example-ajax" href="${ctx}/member/loadMembersInfo.do?uid=${mem.uid}" rel="external nofollow" style="400px" inputMessage="请输入会员编号(可部分匹配)">
     <option selected="selected" value="666">沉默王二</option>
    </select>

    Java端通过name属性可获得select的value值。

    设置class为js-data-example-ajax,页面加载时对该组件进行select2的初始化。

    href属性为ajax提供后台检索的URL。

    style设置组件的宽度。

    inputMessage属性定制个性化的提示语,默认的英文版为Please enter 1 or more characters,中文国际化为“请再输入至少1个字符”,都不太能满足个性化需求,所以需要改,后面介绍。
    提供一个默认的option,页面没检索之前显示。

    第二步、select2组件化,注释写得很详细了哦

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    <script type="text/javascript">
     $(function() {
      $("select.js-data-example-ajax").each(
      function() {
       var $this = $(this);
       $this.select2({
        language : "zh-CN",// 指定语言为中文,国际化才起效
        inputMessage : $this.attr("inputMessage"),// 添加默认参数
        ajax : {
         url : $this.attr("href"),
         dataType : 'json',
         delay : 250,// 延迟显示
         data : function(params) {
          return {
           username : params.term, // 搜索框内输入的内容,传递到Java后端的parameter为username
           page : params.page,// 第几页,分页哦
           rows : 10// 每页显示多少行
          };
         },
         // 分页
         processResults : function(data, params) {
          params.page = params.page || 1;
          return {
           results : data.data,// 后台返回的数据集
           pagination : {
            more : params.page < data.total// 总页数为10,那么1-9页的时候都可以下拉刷新
           }
          };
         },
         cache : false
        },
        escapeMarkup : function(markup) {
         return markup;
        }, // let our custom formatter work
        minimumInputLength : 1,// 最少输入一个字符才开始检索
        templateResult : function(repo) {// 显示的结果集格式,这里需要自己写css样式,可参照demo
         // 正在检索
         if (repo.loading)
          return repo.text;
         var markup = repo.username;
         markup += repo.realname;
         var markup = "<div class='select2-result-repository clearfix'>" + "<div class='select2-result-repository__avatar'><img src='"
           + repo.headimgUrl + "' /></div>" + "<div class='select2-result-repository__meta'>"
           + "<div class='select2-result-repository__title'>" + repo.username + "</div>";
         if (repo.realname) {
          markup += "<div class='select2-result-repository__description'>" + repo.realname + "</div>";
         }
         markup += "<div class='select2-result-repository__statistics'>"
           + "<div class='select2-result-repository__forks'><i class='fa fa-user'></i> 下级会员数" + repo.children_count + " </div>"
           + "</div>" + "</div></div>";
         return markup;
        },
        templateSelection : function(repo) {
         return repo.realname || repo.text;
        }// 列表中选择某一项后显示到文本框的内容
       });
      });
     });
    </script>

    第三步、Java端接收参数并返回结果集,不用我强调,这步很重要

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    @RequestMapping(value = "loadMembersInfo")
    public void loadMembersInfo(HttpServletRequest request, HttpServletResponse response) throws IOException {
     Integer uid = StrUtil.parseStringToInt(request.getParameter("uid"));
     Members mem = this.memberService.selectByPrimaryKey(uid);
     // 分页参数的转换,需要和前台select2进行匹配,下文放代码
     BaseConditionVO vo = getBaseConditionVOForTable(request);
     vo.addParams("username", StrUtil.getUTF8String(request.getParameter("username")));
     vo.addParams("uid", uid);
     // 封装结果集,和前台select2也是匹配的。
     PageGrid page = createPageGrid(this.membersMapper.getPromoterList(vo, vo.createRowBounds()), vo,
       this.membersMapper.searchPromoterTotalCount(vo));
     // 以json格式写入到response
     out(page, response);
    }

    接下来,把关键的源码贴出来,可能和你的项目不吻合,但可以参考。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    BaseConditionVO.Java
    public class BaseConditionVO {
     public final static int PAGE_SHOW_COUNT = 50;
     private int pageNum = 1;
     private int numPerPage = 0;
     private int totalCount = 0;
     private String orderField;
     private String orderDirection;
     /**
      * @Fields ps : 对参数类型进行封装.
      */
     private Map<String, Object> mo = new HashMap<String, Object>();
     public int getPageNum() {
      return pageNum;
     }
     public void setPageNum(int pageNum) {
      this.pageNum = pageNum;
     }
     public int getNumPerPage() {
      return numPerPage > 0 ? numPerPage : PAGE_SHOW_COUNT;
     }
     public void setNumPerPage(int numPerPage) {
      this.numPerPage = numPerPage;
     }
     public String getOrderField() {
      return orderField;
     }
     public void setOrderField(String orderField) {
      this.orderField = orderField;
     }
     public String getOrderDirection() {
      return "desc".equals(orderDirection) ? "desc" : "asc";
     }
     public void setOrderDirection(String orderDirection) {
      this.orderDirection = orderDirection;
     }
     public int getTotalCount() {
      return totalCount;
     }
     public void setTotalCount(int totalCount) {
      this.totalCount = totalCount;
     }
     public int getStartIndex() {
      int pageNum = this.getPageNum() > 0 ? this.getPageNum() - 1 : 0;
      return pageNum * this.getNumPerPage();
     }
     public RowBounds createRowBounds() {
      RowBounds ro = new RowBounds(this.getStartIndex(), this.getNumPerPage());
      return ro;
     }
     /**
      * @Title: addParams
      * @Description: 添加查询条件
      * @param key
      * @param value
      */
     public void addParams(String key, Object value) {
      this.getMo().put(key, value);
     }
     /**
     * @Title: getParams
     * @Description: 获取查询条件
     * @param key
     * @return
     */
     public Object getParams(String key) {
      return this.getMo().get(key);
     }
     /**
      * @return the mo
      */
     public Map<String, Object> getMo() {
      return mo;
     }
     /**
      * @param mo
      *   the mo to set
      */
     public void setMo(Map<String, Object> mo) {
      this.mo = mo;
     }
    }

    selec2的分页和Java端分页参数匹配

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    protected BaseConditionVO getBaseConditionVOForTable(HttpServletRequest req) {
     BaseConditionVO vo = new BaseConditionVO();
     // 当前页
     int currentPage = StrUtil.parseStringToInt(req.getParameter("page"));
     // 一页显示多少行
     int sizes = StrUtil.parseStringToInt(req.getParameter("rows"));
     // 排序
     String sortOrder = StrUtil.getString(req.getParameter("sord"));
     String sortCol = StrUtil.getString(req.getParameter("sidx"));
     vo.setNumPerPage(sizes);
     vo.setPageNum(currentPage);
     vo.setOrderField(sortCol);
     vo.setOrderDirection(sortOrder);
     return vo;
    }

    Java端到select2端的数据封装

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    @XStreamAlias("pageGrid")
    @SuppressWarnings("rawtypes")
    public class PageGrid {
     private int page;
     // 总页数,和select2的processResults.pagination匹配
     private int total;
     private int records;
     // 数据结果集,和select2的processResults.results匹配
     private List data;
     public int getPage() {
      return this.page;
     }
     public void setPage(int page) {
      this.page = page;
     }
     public int getTotal() {
      return this.total;
     }
     public void setTotal(int total) {
      this.total = total;
     }
     public int getRecords() {
      return this.records;
     }
     public void setRecords(int records) {
      this.records = records;
     }
     public List getData() {
      return this.data;
     }
     public void setData(List data) {
      this.data = data;
     }
    }

    MySQL获取的数据源和PageGrid进行转换匹配

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    protected PageGrid createPageGrid(List list, BaseConditionVO vo, int searchTotalCount) {
     PageGrid pageGrid = new PageGrid();
     // 数据
     pageGrid.setData(list);
     // 当前页
     pageGrid.setPage(vo.getPageNum());
     // 总数目
     pageGrid.setRecords(list.size());
     // 总页数
     int total = 0;
     if (pageGrid.getRecords() != 0) {
      total = searchTotalCount % vo.getNumPerPage() == 0 ? searchTotalCount / vo.getNumPerPage()
        : searchTotalCount / vo.getNumPerPage() + 1;
     }
     pageGrid.setTotal(total);
     return pageGrid;
    }

    mybatis的分页,超简单,只要设置了createRowBounds,mybatis就会自动为你分页,这个就厉害了。

    1
    List getPromoterList(BaseConditionVO vo, RowBounds createRowBounds);

    sql语句,这里的关键点是必须要回传id(m.uid as id)到select2.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <select id="getPromoterList" resultType="hashmap" parameterType="map">
     select
     m.uid as id,
     convert(m.username,char) username,
     m.realname,
     m.children_count,
     m.headimgUrl
     from
     members m
     where m.deleteflag=0
     <if test="mo.username != ''">and m.username like CONCAT('%', '${mo.username}', '%')</if>
     <choose>
      <when test="orderField !=null and orderField !=''">
       ORDER BY ${orderField}
       <if test="orderDirection != null and orderDirection != ''">${orderDirection}</if>
      </when>
      <otherwise>
       order by m.username DESC
      </otherwise>
     </choose>
    </select>

    你是不是没看见mysql的分页limit,嗯,这里无须关注,这就是框架要为我们做的事情。

    总数

    1
    int searchPromoterTotalCount(BaseConditionVO vo);

    count(0)就好

    1
    2
    3
    4
    5
    6
    7
    <select id="searchPromoterTotalCount" resultType="java.lang.Integer" parameterType="map">
     select count(0) as a
     from
     members m
     where m.deleteflag=0
     <if test="mo.username != ''">and m.username like CONCAT('%', '${mo.username}', '%')</if>
    </select>

    out输出到response中

    1
    2
    3
    4
    5
    6
    protected void out(Object result, HttpServletResponse response) throws IOException {
     ServletOutputStream out = response.getOutputStream();
     ObjectMapper objectMapper = new ObjectMapper();
     objectMapper.writeValue(out, result);
     out.flush();
    }

    到这,select2的remote功能在代码部分就完全贴出来完了。

    不过,我最后还是要强调几个点:

    1.分页的参数Java端和select2一定要对照起来。

    2.回传的数据一定要传递一个id回来,否则回来的列表不能选中,为什么呢?调查select2的源码可以知道。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    Results.prototype.option = function (data) {
     var option = document.createElement('li');
     option.className = 'select2-results__option';
     var attrs = {
      'role': 'treeitem',
      'aria-selected': 'false'
     };
     if (data.disabled) {
      delete attrs['aria-selected'];
      attrs['aria-disabled'] = 'true';
     }
    // id为空的情况下,删除的aria-selected,而aria-selected恰好又是列表选中的关键属性。
    // 这个就是个坑,只能这么说,select2给出的api上完全不讲这点,我去!!!!!!!
     if (data.id == null) {
      delete attrs['aria-selected'];
     }
     ......
    }

    3.form表单如何获取select2的值?答案是,1.返回结果集必须有id,2.input标签上必须要name属性。

    4.如何自定义inputMessage呢?

    在select2.js中找到以下代码,注意注释部分

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    S2.define('select2/data/minimumInputLength',[
    ], function () {
     function MinimumInputLength (decorated, $e, options) {
     this.minimumInputLength = options.get('minimumInputLength');
     // inputMessage
     this.inputMessage = options.get('inputMessage');
     decorated.call(this, $e, options);
     }
     MinimumInputLength.prototype.query = function (decorated, params, callback) {
     params.term = params.term || '';
     if (params.term.length < this.minimumInputLength) {
      this.trigger('results:message', {
      message: 'inputTooShort',
      args: {
       minimum: this.minimumInputLength,
       input: params.term,
       inputMessage : this.inputMessage, // inputMessage,传递给i18n
       params: params
      }
      });
      return;
     }
     decorated.call(this, params, callback);
     };
     return MinimumInputLength;
    });

    select2.js中defaults中增加上inputMessage

    1
    2
    3
    4
    5
    6
    7
    this.defaults = {
    ...
     minimumInputLength: 0,
     inputMessage: '',
     maximumInputLength: 0,
     ...
    };

    然后在zh-CN.js文件中修改inputTooShort方法

    1
    2
    3
    4
    5
    6
    7
    8
    inputTooShort : function(e) {
     if (e.inputMessage) {
      return e.inputMessage;// 增加inputMessage
     } else {
      var t = e.minimum - e.input.length, n = "请再输入至少" + t + "个字符";
      return n
     }
    },

    原文链接:http://blog.csdn.net/qing_gee/article/details/72519313

  • 相关阅读:
    线程间操作无效: 从不是创建控件“Control Name'”的线程访问它问题的解决方案及原理分析
    C#打印图片
    javascript 地址栏写法
    SQLServer获取Excel中所有Sheet
    C#多页打印实现
    clear在CSS中的妙用
    mitmproxy使用总结
    本地回路抓包问题
    博客园界面优化
    CentOS基于MySQL提供的Yum repository安装MySQL5.6
  • 原文地址:https://www.cnblogs.com/keyi/p/6971143.html
Copyright © 2011-2022 走看看