列表组件抽象(3):分页和排序管理说明

544 查看

本文介绍列表组件中我对分页和排序的抽象思路。

先来说分页,因为之前写过一篇简单封装分页功能pageView.js,这次封装分页时的思路基本与那篇博客的想法完全一样,只不过考虑到我要写的列表组件,还有其它的分页形式,比如点击加载更多进行翻页,基于浏览器标准的scroll事件进行翻页,基于iscroll插件派发的scroll事件进行分页。于是我在该文的基础上进一步抽象,将分页的一些公共逻辑提炼到一个基类中,仅仅将UI与分页控制的逻辑留给子类实现,这样能够最大程度地简化代码。这个基类的最终实现是:https://github.com/liuyunzhuge/blog/blob/master/form/src/js/mod/listView/base/pageViewBase.js,它其实就是简单封装分页功能pageView.js这篇博客中pageView.js分离出来的,所以如果想要去了解这个文件的说明,可以访问之前的那篇博客。

当我把分页的一些公共逻辑抽象到pageViewBase之后,在简单封装分页功能pageView.js这篇文章中的pageView.js就会变得特别简洁,我最终的实现是:https://github.com/liuyunzhuge/blog/blob/master/form/src/js/mod/listView/simplePageView.js。当你查看pageViewBase.js的源码和simplePageView.js的源码,会发现它们合起来就是简单封装分页功能pageView.js里面的pageView.js。

其它的分页组件实现有:

基于浏览器标准的scroll事件进行翻页,https://github.com/liuyunzhuge/blog/blob/master/form/src/js/mod/listView/scrollPageView.js

基于iscroll插件派发的scroll事件进行分页,https://github.com/liuyunzhuge/blog/blob/master/form/src/js/mod/listView/iscrollPageView.js

这两个分页组件其实跟simplePageView没什么大的不同,只是分页使用到的事件不同,另外就是由于涉及到滚动翻页,所以还有一个何时进行自动翻页的判断问题,这个判断问题我会在后面的文章介绍滚动分页列表组件的时候再来说明。

再来看排序

相比之下,排序会比分页麻烦一些。做排序管理的目的在于,列表为用户提供数据的时候,为了更有针对性的查看数据,用户一般会希望能够主动地控制列表的排序规则,所以得考虑排序管理的功能,以便列表能够实现自定义的排序。在用户做了排序操作之后,我们需要告诉后台当前排序操作结果对应的排序字段以及每个字段对应的排序值。由于有可能有多列排序的情况,所以传递排序参数时,还得按排序操作时的顺序,组织好排序字段的顺序,以便后台能够按照用户的操作结果,来进行排序处理。类似下面这样的数据结构就可以正确地反映一个排序操作的结果:

字段在数组中的先后关系即可代表排序时的先后关系。只要能够得到这样一个结构,就能把转成json格式的字符串传递给后台进行处理。最终这个数据结构对应到数据库中的排序规则时,就是这样的:

 从排序操作上来说,常见的table插件是这么做的:

1. 如果仅仅是鼠标单击排序列,那么执行的就是单列排序操作。只要按照 不排序->升序、升序->降序、降序->不排序的切换规则,在鼠标单击排序列之后,改变该列对应的排序字段的排序方式,然后触发查询即可。传递到后台时,排序参数最多包含一个字段。

2. 如果在鼠标单击排序列之前,用户先摁住了shift键,再做点击操作,此时用户执行的就是多列排序操作,在shift键摁住期间,先点击的排序列对应的字段在排序结果中的顺序靠前,后点击的靠后。单个排序列还是按照 不排序->升序、升序->降序、降序->不排序的切换规则来更改自身的排序方式,但是在单击完之后并不会立即触发列表查询,而是要等到shift键释放之后,再来查询。传递到后台时,排序参数可能包含多个字段。

按照前面的这个需求,我的实现思路时:先把排序参数的管理和排序操作的控制分开,写成两个组件;排序参数的管理组件仅负责排序字段的数据这一层级的控制,不与任何UI打交道;排序操作的管理组件负责与DOM交互,响应用户的键鼠操作,内部实例化一个排序参数管理的组件,利用这个组件实例来完成对排序字段的修改。这么做的好处在于将数据与UI分离,其实也就是表现与行为分离,简化UI层的逻辑,让代码看起来更加清晰。

最后考虑到不同的列表组件,可能有不同的排序UI控制逻辑,所以也决定把排序组件抽象出一个基类,像pageViewBase一样,把一些排序组件公共的逻辑出现出来,比如事件监听,启用禁用以及排序参数管理组件的实例化等。最终我得到了以下2个核心的排序组件相关的文件:

排序参数管理组件:https://github.com/liuyunzhuge/blog/blob/master/form/src/js/mod/listView/base/sortFields.js

排序控制管理组件的基类:https://github.com/liuyunzhuge/blog/blob/master/form/src/js/mod/listView/base/sortViewBase.js

下面我把这两个文件的一些要点一一说明。

先说sortFields。

这个文件比sorViewBase还长,可想而知,如果我把sortFields的逻辑不分离,直接写在sortViewBase里面,sortViewBase的复杂性肯定会增加不少。为了了解这个组件的作用,我先用几段简单的代码来演示它的用法,虽然在实际使用中,这个组件并不需要直接实例化,但是它还是可以直接实例化的,不然就无法为sortView组件所用了。

通过下面的方式来实例化一个sortFields的组件。

先说config这个option,其它的介绍后面的用法再补充。config用来配置排序管理组件要管理的排序字段。用数组的形式来配置多个排序字段,单个排序字段的排序定义用一个js的字面量对象来配置。用field属性来定义排序字段的名称;用value属性来配置该字段初始化时的排序方式;用type属性来配置该字段的数据类型,如string,int等,这个有可能在后台会需要;用order属性来配置该字段在排序规则中的初始化位置。如以上config,在初始化后,实际上对应的排序规则就是:

为啥是email在前,contact在后面,这个就是order属性的作用了。

sortFields组件提供了一个getConfig的实例方法,这个方法返回所有排序字段的当前状态:

459873-20160919104853137-202205033

在通过后面要介绍的changeState方法,改变了单个排序字段的排序方式后,我们可以在其它位置通过调用getConfig方法,获取排序字段最新的状态,从而更新UI:

459873-20160919104855090-689485306

比如simpleSortView里面的render方法就是这么做的: