资讯专栏INFORMATION COLUMN

miniui datagrid 的客户端分页解决方案

darkbug / 2663人阅读

摘要:官方的解决方案展示了客户端分页解决方案的基本思想,但是这个示例太过简单。原来是向设置了需要显示的所有数据行,不管分页比如可以一次显示出来条数据而现在,如果设置的数据量过大,则需要通过客户端分页来逐页显示。

官方的解决方案

官方在“在线示例”中给了一个简单的 client pagination 解决方案,代码就不贴了,这里说说它的基本思想和处理过程。

首先,是绑定一个 preload 事件,在这个事情中设置 event.cancel = true,阻止 datagrid 在翻页的时候向服务器请求加载数据。

那么数据从哪来呢?当然只有在外部写一个 ajax 过程获取了。不过取得的数据并不直接交给 datagrid,而是缓存起来,放在 dataResult 中。

现在继续说 preload,除了阻止 datagrid 向服务器请求数据之外,preload 还需要从缓存中找到页码对应的数据行,通过 setData 设置给 datagrid 渲染出来。OK,这个事情是交给自定义函数 fillData 来实现的。当然,这里还要干点与页面相关的事情,就是 setTotalCount()setPageIndex()setPageCount()

官方的解决方案展示了 miniui datagrid 客户端分页解决方案的基本思想,但是这个示例太过简单。如果,想把之前的服务端分页改成客户端分页该怎么办?原来已经存在对 load()setData() 等的调用,现在怎样以最小的代码改动来实现客户端分页?

class ClientPagination

就上面的问题,首先能想到的,就是保留原有 load()setData() 的接口,但是要改变它们的行为。

load() 原有行为是提交了〔XXX参数〕,从服务器加载指定页的数据;而现在需要改为加载所有数据。

setData() 原来是向 datagrid 设置了需要显示的所有数据行,不管分页(比如可以一次显示出来200条数据);而现在,如果设置的数据量过大,则需要通过客户端分页来逐页显示。

JavaScript 语言是动态有,这使得替换方法成为可能,这是很多静态语言做不到的事情。而替换方法也是解决这个问题时最容易想到的办法。当然除此之外,还得庆幸 miniui 没有采用 jQuery 扩展的方式(如 $grid.datagrid("setData", ...))来实现组件。

替换方法成为可能,但是原有方法还是得保留,因为我们需要通过原有方法来操作 datagrid。所以 ClientPagination 类应该是这个样子:

ClientPagination 的基本结构

注:本文中所有代码都是 ES6 语法

const METHODS = ["setData", "load"];

class ClientPagination {
    constructor(datagrid) {
        this._datagrid = datagrid;
        this._origin = {};
        this.setup();
    }
    
    setup() {
        // TODO 暂存 this._datagrid 的 load、setData 等方法
        // 并为 this._datagrid 设置新方法和注册事件
    }

    destroy() {
        // TODO 恢复 this._datagrid 的方法,注销事件
    }
    
    onBeforeLoad() {
        // 根据官方的解决方案而来
        e.cancel = true;
        let pageIndex = e.data.pageIndex;
        let pageSize = e.data.pageSize;
        this.setPageData(pageIndex, pageSize);
    }

    // 参照 datagrid.load 的函数签名
    load(params, success, fail) {
        // TODO 实现加载数据,并保存到 this._data 中
        // 然后调用 this.setData() 保存和显示数据
    }

    setData(data) {
        // TODO 保存 data 到 this._data 中,
        // 然后调用 this.setPageData() 显示当前页的数据
    }
    
    setPageData(pageIndex, pageSize) {
        // TODO 从缓存的 this._data 中按 pageIndex 和 pageSize 取出要显示的数据行
        // 然后通过 this._origin.setData() 设置在 datagrid 中
    }
}
设置和解除客户端分页

其中 setupdestroy 为分别为 datagrid 绑定和解绑客户端分页处理

    setup() {
        const grid = this._datagrid;
        const original = this._origin = {};

        METHODS.forEach(name => {
            // 暂存原方法
            origin[name] = grid[name].bind(grid);
            // 替换为本类中定义的新方法
            grid[name] = this[name].bind(this);
        });

        // 暂存事件处理函数,以便后面注销
        this._onBeforeLoad = this.onBeforeLoad.bind(this);
        grid.on("beforeload", this._onBeforeLoad);
    }

    destroy() {
        this._origin = {};
        this._datagrid.un("beforeload", this._onBeforeLoad);
        this._datagrid = null;
    }
来自官方示例中的关键代码

onBeforeLoad 以及 setPageData 是参照官方解决方案中的 beforeload 事件和 fillData 方法写的。onBeforeLoad 的代码在上面已经有了,现在是 setPageData 的代码

    setPageData(pageIndex, pageSize) {
        const allData = this._data;
        let start = pageIndex * pageSize;
        if (start >= allData.length) {
            start = 0;
            pageIndex = 0;
        }
        const end = Math.min(start + pageSize, allData.length);

        const pageData = [];
        for (let i = start; i < end; i++) {
            pageData.push(allData[i]);
        }

        const grid = this._datagrid;
        grid.setTotalCount(allData.length);
        grid.setPageIndex(pageIndex);
        grid.setPageSize(pageSize);
        this._origin.setData(pageData);
    }
改写 load

load 方法需要用 ajax 调用来替换原来的 load 方法

    load(params, success, fail) {
        const grid = this._datagrid;
        const url = grid.getUrl();

        const settings = {
            type: "post",
            dataType: "json",
            data: params || {}
        };

        $.ajax(url, settings)
            .then(data => {
                this.setData(data);
                if (typeof success === "function") {
                    success(data);
                }
            }, () => {
                if (typeof fail === "function") {
                    fail();
                }
            });
    }
改写 setData

setData 也进行了替换,参数是整表的数据,但只能显示当前页的数据

    setData(data) {
        const rows = Array.isArray(data)
            ? data
            : (data.data || []);

        this._data = rows;
        this.setPageData(this._datagrid.getPageIndex(), this._datagrid.getPageSize());
    }
应用

为了方便封装,再加一个静态方法

    static wrap(datagrid) {
        return new ClientPagination(datagrid);
    }

现在只需要在页面初始化(或其它合适的初始化位置)加上

ClientPagination.wrap(mini.get("datagridId"));

如果需要 destroy,可以这样

var cpBlabla = ClientPagination.wrap(mini.get("datagridId"));
....
cpBalbal.destory();
小结

通过 ClientPagination 的封装,不需要改变原有的业务代码和设置,就可以实现 miniui datagrid 的客户端分页。

但是这个实现只是解决了当前的问题,如果有新的需求:

当页码在前三页的时候用客户端分页,以减少数据加载次数,翻到后面的时候需要用服务器端分页

又该如何?是不是该出个续集?

续集在这里

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/91063.html

相关文章

  • miniui datagrid 户端分页解决方案 - CS结合

    摘要:在前一篇,的客户端分页解决方案中留下了一个问题如果前三页只需要加载一次数据,采用客户端分页,之后的每一页都仍然从服务器获取,应该怎么办现在就来改造,让它实现这个功能。所以正确的解决办法是试验一下就能证明它的正确性。 在前一篇,miniui datagrid 的客户端分页解决方案 中留下了一个问题:如果前三页只需要加载一次数据,采用客户端分页,之后的每一页都仍然从服务器获取,应该怎么办?...

    shixinzhang 评论0 收藏0
  • 细说nui之datagrid

    摘要:表格的刷新保留查询条件的刷新当前分页的数据更新,请使用也可以使用获取当前接口请求的参数。 本期我们要讲述一下最常见的布局————表格:如何引入datagrid组件(在文章的末尾)来个demo,调用的代码 let options = { container:.con,//表格的容器 paging:{//分页的相关配置,其他参数配置参考[诺诺组件之分页(旧版)][1] ...

    LeanCloud 评论0 收藏0
  • fsLayui数据表格使用

    摘要:是一个基于的快速开发插件,支持数据表格增删改查操作,提供通用的组件,通过配置实现数据请求,减少前端重复开发的工作。 fsLayui 是一个基于layui的快速开发插件,支持数据表格增删改查操作,提供通用的组件,通过配置html实现数据请求,减少前端js重复开发的工作。 GitHub下载 码云下载 测试环境地址:http://fslayui.itcto.cn css和js引用 公...

    Joyven 评论0 收藏0
  • fsLayui数据表格使用

    摘要:是一个基于的快速开发插件,支持数据表格增删改查操作,提供通用的组件,通过配置实现数据请求,减少前端重复开发的工作。 fsLayui 是一个基于layui的快速开发插件,支持数据表格增删改查操作,提供通用的组件,通过配置html实现数据请求,减少前端js重复开发的工作。 GitHub下载 码云下载 测试环境地址:http://fslayui.itcto.cn css和js引用 公...

    charles_paul 评论0 收藏0
  • EasyUI datagrid问题整理

    摘要:什么是是一种基于和的用户界面插件集合。为创建现代化,互动,应用程序,提供必要的功能。是个完美支持网页的完整框架。很简单但功能强大的。返回则取消该动作。该函数有下列参数要传递到远程服务器的参数对象。当检索数据成功时调用的回调函数。 什么是easyUI easyui是一种基于jQuery、Angular.、Vue和React的用户界面插件集合。easyui为创建现代化,互动,JavaScr...

    megatron 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<